2

Say we have a situation like this:

base.h:

class Base { };

derived.h:

#include "base.h"
class Derived : public Base { };
extern Derived *variable;

derived.cpp:

#include "derived.h"
Derived *variable; 

Is it correct to declare variable as a pointer to Base in elsewhere.cpp?

class Base;
extern Base *variable;

The C++Builder linker doesn't complain and everything seems to work. Is this safe and correct according to the standard, or should every declaration of variablebe of the same type?

4

3 に答える 3

2

これがうまくいかない可能性のあるいくつかの方法を次に示します (未定義の動作であることは別として、つまり、発生している動作の 1 つに依存することさえすべきではありません)。

  • コンパイラは、変数のマングリングの型部分を作成する場合があります。どうやら C++Builder にはありませんが、MSVC にはあると確信しています。その場合、リンカー エラーが発生します。
  • ある時点Derivedで が次のように変更されたとします。

    class Derived : public Something, public Base {};

    whereSomethingが空でない場合、ほとんどの ABI では、 a にDerived*キャストされると値が変更されますBase*。ただし、グローバル変数のエイリアシングはこの調整をバイパスし、 をBase*指していない を残しますBase

  • コンパイラーは、実際には他の手段で ODR 違反を検出し、エラーを出力する場合があります。

  • OtherDerivedタイプのオブジェクト(これも から派生しているが、 から派生してBaseいないDerived) を に割り当てるとどうなりますvariableか? それを と見なすプログラムの部分は、Derived*それが を指すことを期待していDerivedますが、実際には を指していOtherDerivedます。このようなコードで最も魅力的な効果を見ることができます。バージョンを呼び出しながら、仮想関数をfoo呼び出すとバージョンが呼び出されるように設定できます。可能性は無限大。Derivedfoo2OtherDerived
于 2013-06-18T13:37:09.413 に答える
2

大丈夫じゃない。名前variableが同じエンティティを参照することになっている場合 (それは であるため、そうですextern)、同じタイプである必要があります。そうしないと、ODR (One Definition Rule) に違反することになります。

于 2013-06-18T13:20:01.267 に答える