4

私はこの2つのクラスを持っています:

class   IBaseA
{
public:
  virtual bool  sayHello(std::string&) = 0;
  ~IBaseA(){}
};                                                                                                   

class   BaseA: public IBaseA
{
public:
  virtual bool  sayHello(std::string &str)
  {
    std::cout << "Hello " << str << std::endl;
    return (true);
  }
  BaseA(){}

};

なぜ私がそのようなことをすることができないのか説明してもらえますか

bool  (IBaseA::*ptr)(std::string&) = &BaseA::sayHello;

エラー: 「bool (BaseA:: )(std::string&) {aka bool (BaseA:: )(std::basic_string&)}」を「bool (IBaseA:: )(std::string&) {aka bool 」に変換できません(IBaseA:: )(std::basic_string&)}' 初期化中

なんでこんなことができないのかわからない。

しかし、割り当てを変更すると

bool  (IBaseA::*ptr)(std::string&) = &IBaseA::sayHello;

その後、このポインターを問題なく使用できます

BaseA A;
(A.*ptr)(str);

編集:答えてくれてありがとう、私はすべてのアドレスがvtableにあるので、私がウィキペディアから理解したことによると、それらは同じ場所であると考えていました.

4

4 に答える 4

5

ポインターからメンバーへの変換は、通常のポインター変換とは反対に機能します。派生クラスへのポインターを基底クラスへのポインターに変換できますが、その逆はできません。基本クラスのメンバーへのポインターを派生クラスのメンバーへのポインターに変換できますが、その逆はできません。

変換が有効かどうかを常に考えてください。

プレーン ポインター: のすべてのインスタンスBaseAは のインスタンスでIBaseAあるため、変換は有効です。すべてのIBaseAインスタンスがBaseAインスタンスであるとは限らないため、他の方法で変換することはできません。

メンバーへのポインター: のすべてのメンバーはIBaseAにも存在するため、 のメンバーへのポインターをBaseAのメンバーへのポインターに変換できます。ただし、のすべてのメンバーがに存在するわけではないため、逆の変換はできません。IBaseABaseABaseAIBaseA

于 2013-06-21T12:41:59.797 に答える
1

2 つのメンバーへのポインター型T C1::*P1and T C2::*P2(T は関数型である場合があります) が与えられた場合、C2 が C1 から派生している場合にのみ、P1 を P2 に変換できます。これは、アップキャストしかできないオブジェクトへのポインターの逆であることに注意してください。

その理由は、基本クラスのメンバーへのポインターがある場合、サブクラスもそのメンバーを継承しているため、そのメンバーも持つことが保証されているためです。その逆は適用されません。

これが基本的な型変換規則です。そこにある特定のポインターがたまたま基本クラスに存在する仮想関数のオーバーライドであるという理由だけで、それは変わりません。

于 2013-06-21T12:42:21.833 に答える
1

直観に反するように思えるかもしれませんが、派生型のメンバーへのポインターをベースへのメンバーへのポインターに変換することはできません。正しい変換は逆です。メンバーへのポインターをベースに、メンバーへのポインターを派生に変換できます。

その理由は、ベースが持っている場合、派生型がそのメンバーを持つことが保証されているためですが、その逆は真ではありません (つまり、派生型へのメンバーへのポインターは、追加されたが存在しないメンバーを参照できます)。ベースで)。

見落としている可能性があるもう 1 つの点は、メンバーへのポインター関数が多態的であることです。つまり、格納することができ、&IBase::sayHelloそれBase::sayHelloが適用されるメンバーの型がBase.

于 2013-06-21T12:48:28.560 に答える
1

本当の答えはおそらく「言語仕様でできないと書かれているから」ですが、何をしようとしているのかを考えてみてください。

bool  (IBaseA::*ptr)(std::string&) = &BaseA::sayHello;

基本的に、これは次のようになります。 IBaseA のメンバ関数へのポインタである ptr という変数が必要で、BaseA のメソッド 'sayHello' を指すようにします。

はい、BaseA の sayHello メソッドは IBaseA の sayHello メソッドをオーバーライドしますが、それでもこれらは異なるメソッドです。ポインターを使用して、実際には BaseA ではないIBaseA 型のオブジェクトのメソッドを呼び出そうとした場合を想像してみてください。これは構文的に許可されていますが、どうなるでしょうか?

つまり、派生クラスのメンバーへのポインターを取得し、それを基本クラスのメンバーを指すように宣言された変数に割り当てると、静的タイプ セーフが破られます。

于 2013-06-21T12:45:37.407 に答える