59

次の例が「0」を出力する理由と、期待どおりに「1」を出力するには何を変更する必要がありますか?

#include <iostream>
struct base {
   virtual const int value() const {
      return 0;
   }
   base() {
      std::cout << value() << std::endl;
   }
   virtual ~base() {}
};

struct derived : public base {
   virtual const int value() const {
      return 1;
   }
};

int main(void) {
   derived example;
}
4

7 に答える 7

9

実は、この動作を取得する方法があります。「ソフトウェアのすべての問題は、ある程度の間接化で解決できます。」

/* Disclaimer: I haven't done C++ in many months now, there might be a few syntax errors here and there. */
class parent
{
public:
     parent( ) { /* nothing interesting here. */ };
protected:
     struct parent_virtual
     {
         virtual void do_something( ) { cout << "in parent."; }
     };

     parent( const parent_virtual& obj )
     {
          obj.do_something( );
     }
};

class child : public parent
{
protected:
     struct child_virtual : public parent_virtual
     {
         void do_something( ) { cout << "in child."; }
     };
public:
      child( ) : parent( child_virtual( ) ) { }
};
于 2009-01-31T08:07:10.630 に答える
3

コンストラクターから仮想メソッドをポリモーフィックに呼び出すべきではありません。代わりに、オブジェクトの構築後にそれらを呼び出すことができます。

コードは次のように書き直すことができます

struct base {
   virtual const int value() const {
      return 0;
   }
   base() {
      /* std::cout << value() << std::endl; */
   }
   virtual ~base() {}
};

struct derived : public base {
   virtual const int value() const {
      return 1;
   }
};

int main(void) {
   derived example;
   std::cout << example.value() << std::endl;
}
于 2009-01-31T01:15:34.750 に答える
0

一般的なルールは、コンストラクターから仮想関数を呼び出さないことです。

于 2009-01-30T17:40:01.487 に答える
-4

C++ では、コンストラクターから仮想/オーバーライド メソッドを呼び出すことはできません。

さて、これができるのには十分な理由があります。「ソフトウェアでのベスト プラクティス」として、非仮想であっても、コンストラクターから追加のメソッドをできるだけ呼び出さないようにする必要があります。

ただし、ルールには常に例外があるため、「疑似コンストラクター メソッド」を使用してそれらをエミュレートすることをお勧めします。

#include <iostream>

class base {
   // <constructor>
   base() {
      // do nothing in purpouse
   }
   // </constructor>

   // <destructor>
   ~base() {
      // do nothing in purpouse
   }
   // </destructor>

   // <fake-constructor>
   public virtual void create() {
      // move code from static constructor to fake constructor
      std::cout << value() << std::endl;
   }
   // </fake-constructor>

   // <fake-destructor>
   public virtual void destroy() {
      // move code from static destructor to fake destructor
      // ...
   }
   // </fake-destructor>

   public virtual const int value() const {
      return 0;
   }

   public virtual void DoSomething() {
      // std:cout << "Hello World";
   }
};

class derived : public base {
   // <fake-constructor>
   public override void create() {
      // move code from static constructor to fake constructor
      std::cout << "Im pretending to be a virtual constructor," << std::endl;
      std::cout << "and can call virtual methods" << std::endl;
   }
   // </fake-constructor>


   // <fake-destructor>
   public override void destroy() {
      // move code from static destructor to fake destructor
      std::cout << "Im pretending to be a virtual destructor," << std::endl;
      std::cout << "and can call virtual methods" << std::endl;
   }
   // </fake-destructor>

   public virtual const int value() const {
      return 1;
   }
};

int main(void) {
   // call fake virtual constructor in same line, after real constructor
   derived* example = new example(); example->create();

   // do several stuff with your objects
   example->doSomething();

   // call fake virtual destructor in same line, before real destructor
   example->destroy(); delete example();
}

プラスとして、プログラマーはフィールド構造のみに「構造体」を使用し、フィールド、メソッド、コンストラクターなどを含む構造体には「クラス」を使用することをお勧めします...

于 2011-03-28T17:10:17.647 に答える