1

これが私が覚えていたことです:

C++ では、派生クラスが同じ名前のメンバー関数を定義しているが、基本クラスとは異なるシグネチャ (パラメーターなど) を定義している場合、対応するメンバー関数を基本クラスで「非表示」にします。例えば

class Base {
public:
  void virtual f(double x); 
};

class Derived : public Base {
public:
  void f(char c); 
};

int main()
{
  Derived* d = new Derived();
  Base* b = d;
  b->f(65.3);  // call f(double x)
  d->f(65.3);  // call f(char c)
  delete d;
  return 0;
}

私が間違っている場合は修正してください。ただし、C++ で「非表示」と言うと、派生クラスが「f(double x)」を認識できない、つまり、派生クラスに「f(double x)」がないことも意味します。 Base から継承されたメンバー関数として正しいですか?

Java チュートリアルでは、「非表示」は実際には別の意味 (静的クラス メソッドの場合) ですが、インスタンス メソッドの場合は、ベースから継承されたメソッドをオーバーロードできます。この例を見る:継承されたオーバーロードされたメソッドの使用

public class ClassA {
    public void method(Number n) {
        System.out.println("ClassA: " + n + " " + n.getClass());
    }
}

public class ClassB extends ClassA {            
    public void method(Integer d) {
        System.out.println("ClassB: " + d + " " + d.getClass());
    }
}

ClassA a = new ClassB(); 
a.method(3);

C++ タイプの考え方では、C++ の「動的バインディング」と「非表示」のアイデアに基づいて、クラス A の「method(Number n)」が呼び出されるのと同じ結果が得られますが、次のようになります。

  1. Javaで説明する方法がまだわかりません。リンク自体は、「コンパイル時にメソッドシグネチャが選択される」と「実際にはクラスBから呼び出している」を使用して説明しています。でもC++の考え方では前者でもいいのですが、クラスBからの呼び出しではなく、クラスAからの呼び出しのはずですよね?

  2. 継承されたオーバーロードされたメソッドの使用と Java チュートリアルでは、「クラス B」は「クラス A」から関数をオーバーロードすることが許可されており、「クラス B」は実際には「メソッド (数値 n)」と「メソッド (整数 d)」の両方を見ることができます。つまり、C++ と Java ではオーバーロードの扱いが異なりますよね? なんで?C++ の例で言うと、Derived もオーバーロードを許可する場合、'd->f(65.3)' は 'f(char c)' ではなく 'f(double x)' を呼び出します。

ありがとう、

4

2 に答える 2

2

C ++では、非仮想関数ではすべてが静的であるため、非仮想関数では。はありませんdynamic-binding。また、非表示にしても、継承から機能が削除されることはありません。これは次のようなものです。

Mメソッドを次のように定義するとvoid M(int)、コンパイラは関数の内部名Base::Mを。として実装しますvoid Base::M( Base* this, int )。現在、この関数はコードのどこかに実装されており、削除することはできません。これを提供できる限り、呼び出すことができます(実際には、これがなくても呼び出すことができます)。だからChild私はを呼び出すことができBase::M(0);、C++はからに変換thisChild*Base*を呼び出すことができますM。基本クラスの名前に対応する名前で関数を定義するときは、新しいメソッドまたはプロパティのクラスでその名前を使用することをコンパイラーに通知します。usingしかし、あなたは何も削除せず、あなたはの古い定義をに持ってくるためにM使うことができますChild

struct Base {
    void f( int ) {}
};
struct Child : Base {
    void f( char* ) {}
    using Base::f;  // Bring Base::f to this class, so I have f(char*), f(int)
};

f(int)それに加えて、を使用しなくても呼び出すことができますusing

// In the Child class
void test() {
    Base::f('c');  // Call Base::f(char)
}

// Outside of class
Child c;
((Base*)&c)->f('1');
于 2012-10-13T08:17:15.923 に答える
1

これは、私が C++ に期待する動作ではありません。パラメーターが異なるため、基本クラスのメソッドを隠すのではなく、サブクラスがメソッドを単純にオーバーロードすることを期待します。したがって、コンパイラは b->f() を呼び出すときに使用するメソッドを認識しますが、使用できるメソッドは 1 つしかないためです。できない場合は、コンパイル時にキャストを使用する必要があります。あなたの例では、小数点を認識し、charの場合は代わりにdoubleを使用する必要があります。

于 2012-10-13T06:24:54.393 に答える