Конечный класс в С++
class Temp
{
private:
~Temp() {}
friend class Final;
};
class Final : virtual public Temp
{
public:
void fun()
{
cout<<"In base";
}
};
class Derived : public Final
{
};
void main()
{
Derived obj;
obj.fun();
}
Вышеприведенный код пытается достичь не наследуемого класса (final). Но используя вышеприведенный код, объект производного может быть создан, почему?
Желаемая функциональность достигается только в том случае, если ctor сделал частным, мой вопрос в том, почему это невозможно в случае dtor private?
Ответы
Ответ 1
Ну, для этой программы (просьба предоставить правильные, компилируемые примеры)
#include <iostream>
class Temp
{
private:
~Temp() {}
friend class Final;
};
class Final : virtual public Temp
{
public:
void fun() { std::cout<<"In base"; }
};
class Derived : public Final {};
int main() {
Derived obj;
obj.fun();
}
Comeau Online говорит
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 16: error: "Temp::~Temp()" (declared at line 6) is inaccessible
class Derived : public Final {
^
detected during implicit generation of "Derived::Derived()" at line
21
"ComeauTest.c", line 16: error: "Temp::~Temp()" (declared at line 6) is inaccessible
class Derived : public Final {
^
detected during implicit generation of "Derived::~Derived()" at line
21
2 errors detected in the compilation of "ComeauTest.c".
Поскольку, когда я сомневаюсь, я всегда доверяю como (я только что нашел в нем одну ошибку, но многие в других компиляторах), я полагаю, что VC9 (который принимает код) ошибочен. (Из этого void main()
я полагаю, вы тоже используете VC.)
Ответ 2
Обратите внимание, что в С++ 11 существуют неследующие классы с использованием ключевого слова final
, указанного перед списком наследования : base1, base2, ..., baseN
или перед открытием {
, если класс наследует ничего:
class Final final { };
class Derived : public Final { }; // ERROR
С малой магией и некоторыми усилиями по обнаружению компилятора это может быть отвлечено на работу или, в худшем случае, ничего не делать на всех компиляторах.
Ответ 3
Часто задаваемые вопросы по С++ описывают различные способы, но из вашего вопроса, я думаю, вы уже прочитали их.; -)
(Кроме того, main
должен всегда возвращать int
, никогда void
.)
Ответ 4
Любопытно повторяющийся шаблон шаблона. Используйте частное наследование.
template< typename T > class Final
{
protected:
Final() {}
Final( Final const& ) {}
};
class X : private virtual Final<X>
{
// whatever I want to do
};
и вам не удастся извлечь что-либо из X, потому что виртуальное наследование означает, что наиболее производный класс должен построить базовый класс, но он не будет иметь к нему доступа.
(я не тестировал этот код).
Ответ 5
И, конечно, правильный способ сделать это сегодня - использовать ключевое слово final
. Например:
class Foo final {
public:
Foo() {}
~Foo() {}
void bar() {
// ...
}
};
Ответ 6
Производный класс не вызывает частный деструктор базового класса, поэтому он не нуждается в видимости.
Сделать ваши конструкторы частными и предоставить только статическую функцию генератора.
Ответ 7
Я изменил исходный код и проверил этот код в g++:
class Temp
{
private:
Temp() {
cout << "In Temp Class ctor" << endl;
}
~Temp() {}
friend class Final;
};
class Final : virtual public Temp
{
public:
void fun()
{
cout<<"In base";
}
};
class Derived : public Final
{
};
int main()
{
Derived obj;
obj.fun();
return 0;
}
Результат:
$ g++ one.cpp -o one -lm -pthread -lgmpxx -kgmp -lreadline 2 > & 1
one.cpp: В конструкторе "Производный:: Производный()":
one.cpp: 8: 9: error: "Temp:: Temp()" является частным Temp() {
one.cpp: 25: 11: ошибка: в этом контексте class Derived: public Final
one.cpp: 11: 9: error: 'Temp:: ~ Temp()' является приватным ~ Temp() {}
one.cpp: 25: 11: ошибка: в этом контексте class Derived: public Final
one.cpp: 11: 9: ошибка: "Temp:: ~ Temp()" является приватным ~ Temp() {}
Примечание. Лучшая практика не использует void с "main".
Спасибо,