13
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プライベートの場合にそれが達成できないのはなぜですか?

4

7 に答える 7

30

C ++ 11には、継承リストの前、またはクラスが何も継承しない場合は開く前finalに指定されたキーワードを使用して、継承できないクラスが存在することに注意してください。: base1, base2, ..., baseN{

class Final final { };
class Derived : public Final { }; // ERROR

少しのマクロの魔法とコンパイラー検出の努力で、これを抽象化して、すべてのコンパイラーで機能するか、最悪の場合は何もしません。

于 2011-11-20T08:16:37.553 に答える
11

さて、このプログラムの場合(正確でコンパイル可能な例を提供してください)

#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 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を信頼しているので(エラーは1つしか見つかりませんでしたが、他のコンパイラでは多くあります)、VC9(コードを受け入れる)にエラーがあると思います。(それから、void main()あなたもVCを使用していると思います。)

于 2009-09-02T08:39:02.187 に答える
5

C ++ FAQは、これを達成するためのさまざまな方法を説明していますが、あなたの質問から、あなたはすでにそれらを読んだと思います。;-)

(また、main常に返される必要があります。int決して返されませんvoid。)

于 2009-09-02T08:32:52.623 に答える
5

不思議なことに繰り返されるテンプレートパターン。プライベート継承を使用します。

template< typename T > class Final
{
protected:
    Final() {}
    Final( Final const& ) {}
};

class X : private virtual Final<X>
{
  // whatever I want to do
};

また、仮想継承は、最も派生したクラスが基本クラスを構築する必要があるが、それにアクセスできないことを意味するため、Xから何かを派生させることは不可能であることがわかります。

(私はこのコードをテストしていません)。

于 2012-02-01T16:30:39.007 に答える
4

そしてもちろん、今日それを行う適切な方法は、finalキーワードを使用することです。例えば:

class Foo final {
public:
  Foo() {}
  ~Foo() {}

  void bar() {
     // ...
  }
};
于 2013-02-28T16:42:25.350 に答える
0

派生クラスは基本クラスのプライベートデストラクタを呼び出さないため、可視性は必要ありません。

コンストラクターをプライベートにし、静的ジェネレーター関数のみを提供します。

于 2009-09-02T08:35:19.293 に答える
0

投稿された元のコードを変更し、このコードを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:コンストラクター内'Derived :: Derived()':one.cpp:8:9:エラー:'Temp :: Temp()'はプライベートTemp(){

one.cpp:25:11:エラー:このコンテキストクラス内派生:public Final

one.cpp:11:9:エラー:'Temp ::〜Temp()'はプライベートです〜Temp(){}

one.cpp:25:11:エラー:このコンテキストクラス内派生:public Final

one.cpp:11:9:エラー:'Temp ::〜Temp()'はプライベートです〜Temp(){}

注:「main」でvoidを使用しないことをお勧めします。

ありがとう、

于 2013-12-20T08:12:51.387 に答える