3 Stimmen

Wie kann eine Basisklasse die Definition einer reinen virtuellen Funktion einer Elternklasse erfüllen, indem sie die Funktion einer anderen Elternklasse verwendet?

Ich erweitere ein bestehendes C++-Projekt. Ich habe eine Basisklasse, die von zwei Elternklassen abgeleitet ist. Eine der Elternklassen hat eine rein virtuelle Funktion. Ich möchte, dass diese rein virtuelle Funktion durch eine in der anderen übergeordneten Klasse implementierte Funktion definiert wird.

Ich möchte also, dass ein anderes Elternteil die Verpflichtung der Basisklasse erfüllt, eine rein virtuelle Funktion des Elternteils zu definieren. Ich habe zwei Ansätze ausprobiert, die beide zu Compilerfehlern geführt haben.
Irgendwelche Ideen?

Hier ist ein C++-Programm, das meine erste Idee demonstriert, in der Hoffnung, der Compiler würde einfach die base2 Definition von vfunc() .

// This is my first approach, hoping the parent base2 of derived would satisfy the need to define
// base1's pure virtual vfunc.

class base1 {
public:
 virtual int vfunc() = 0;
};

class base2 {
public:
 int vfunc() { return 0;} //defined
};

class derived : public base1, public base2 {
public:
 //empty
};

int main()
{
 derived d;
 base1 & b1 = d;
 int result = b1.vfunc();
 return result;
}

Der Compiler meldet, dass derived ist immer noch eine abstrakte Klasse:

$ gcc a.cc 
a.cc: In function ‘int main()’:
a.cc:26: error: cannot declare variable ‘d’ to be of abstract type ‘derived’
a.cc:18: note:   because the following virtual functions are pure within ‘derived’:
a.cc:7: note:  virtual int base1::vfunc()

Hier ist mein zweiter Versuch:

// This is my second attempt, defining a vfunc in the derived class that calls the other parent.

class base1 {
public:
 virtual int vfunc() = 0;
};

class base2 {
public:
 int vfunc() { return 0; } // defined
};

class derived : public base1, public base2 {
public:
 int vfunc() { return base2::vfunc(); } // call the other parent's vfunc
};

int main()
{
 derived d;
 base1 & b1 = d;
 int result = b1.vfunc();
 return result;
} 

Ich eigentlich erwartet, dass dies für mich zu tun, aber stattdessen der Linker gibt mir eine Reihe von vtable Fehler, die ich nicht verstehe: ( Mac OS 10.6, gcc 4.2.1 )

$ gcc inheritance_tester.cc 
Undefined symbols:
  "vtable for __cxxabiv1::__vmi_class_type_info", referenced from:
      typeinfo for derivedin ccmeHq8C.o
  "___cxa_pure_virtual", referenced from:
      vtable for base1in ccmeHq8C.o
  "___gxx_personality_v0", referenced from:
      _main in ccmeHq8C.o
      base2::vfunc()     in ccmeHq8C.o
      derived::vfunc()     in ccmeHq8C.o
      base1::base1() in ccmeHq8C.o
      base2::base2() in ccmeHq8C.o
      derived::derived()in ccmeHq8C.o
      CIE in ccmeHq8C.o
  "vtable for __cxxabiv1::__class_type_info", referenced from:
      typeinfo for base1in ccmeHq8C.o
      typeinfo for base2in ccmeHq8C.o
ld: symbol(s) not found

3voto

Kirill V. Lyadvinsky Punkte 92957

Sie müssen Folgendes überschreiben vfunc von base1 . Sie können dies wie folgt tun:

class derived : public base1, public base2 {
public:
 using base1::vfunc;
 int vfunc() { return base2::vfunc(); } // call the other parent's vfunc
};

2voto

Adam Rosenfield Punkte 373807

Ihr zweiter Teil des Codes ist in Ordnung, Sie kompilieren ihn nur nicht richtig. Sie müssen mit g++ kompilieren, nicht mit gcc. Wenn Sie mit g++ kompilieren, werden die C++-Laufzeitbibliotheken automatisch eingebunden; wenn Sie mit gcc kompilieren, geschieht dies nicht. Sie können die Bibliotheken auch selbst manuell hinzufügen:

# Option 1: compile with g++
g++ inheritance_tester.cc

# Option 2: compile with gcc and link with the C++ standard libraries
gcc inheritancet_test.cc -lstdc++

0voto

Steve Townsend Punkte 52288

Diese geänderte Version von derived funktionierte bei mir unter Visual C++. Die Implikation für mich ist, dass Sie die beiden geerbten Elemente auseinanderhalten müssen vfunc() s ausdrücklich.

class base1 {
public:
    virtual int vfunc() = 0;
};

class base2 {
public:
    int vfunc() { return 0;} //defined
};

class derived : public base1, public base2 {
public:
    int base1::vfunc() { return base2::vfunc(); } // call the other parent's vfunc
};

int main()
{
    derived d;
    base1 & b1 = d;
    int result = b1.vfunc();
    return result;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X