Конечный класс в С++

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".

Спасибо,