constructors overnemen

Waarom doet deze code:

class A
{
    public: 
        explicit A(int x) {}
};
class B: public A
{
};
int main(void)
{
    B *b = new B(5);
    delete b;
}

Resulteren in deze fouten:

main.cpp: In functie int main() :
main.cpp:13: error: geen overeenkomende functie voor aanroep naar B::B(int) 
main.cpp:8: opmerking: kandidaten zijn: B::B()
main.cpp:8: opmerking: B::B(const B&)

Moet B de constructor van A niet erven?

(dit gebruikt gcc)


Antwoord 1, autoriteit 100%

Als uw compiler de C++11-standaard ondersteunt, is er sprake van een constructorovererving die usinggebruikt (bedoelde woordspeling). Zie Wikipedia C++11-artikelvoor meer informatie. Je schrijft:

class A
{
    public: 
        explicit A(int x) {}
};
class B: public A
{
     using A::A;
};

Dit is alles of niets – je kunt niet slechts enkele constructors erven, als je dit schrijft, erft je ze allemaal. Om alleen geselecteerde te erven, moet je de individuele constructors handmatig schrijven en de basisconstructor van hen oproepen.

In het verleden konden constructors niet worden overgenomen in de C++03-standaard. U moest ze een voor een handmatig overnemen door de basisimplementatie zelf aan te roepen.


Antwoord 2, autoriteit 20%

Constructeurs worden niet geërfd. Ze worden impliciet of expliciet aangeroepen door de onderliggende constructor.

De compiler maakt een standaardconstructor (een zonder argumenten) en een standaard kopieerconstructor (een met een argument dat een verwijzing is naar hetzelfde type). Maar als je een constructor wilt die een int accepteert, moet je deze expliciet definiëren.

class A
{
public: 
    explicit A(int x) {}
};
class B: public A
{
public:
    explicit B(int x) : A(x) { }
};

UPDATE: In C++11 kunnen constructors worden overgenomen. Zie Suma’s antwoord voor details.


Antwoord 3, autoriteit 2%

Dit komt rechtstreeks van Bjarne Stroustrup’s pagina:

Als je dat wilt, kun je jezelf nog steeds in de voet schieten door constructors over te nemen in een afgeleide klasse waarin je nieuwe lidvariabelen definieert die moeten worden geïnitialiseerd:

struct B1 {
    B1(int) { }
};
struct D1 : B1 {
    using B1::B1; // implicitly declares D1(int)
    int x;
};
void test()
{
    D1 d(6);    // Oops: d.x is not initialized
    D1 e;       // error: D1 has no default constructor
}

merk op dat het gebruik van een andere geweldige C++11-functie (initialisatie van leden):

int x = 77;

in plaats van

int x;

zou het probleem oplossen


Antwoord 4, autoriteit 2%

Je moet de constructor expliciet definiëren in B en de constructor expliciet aanroepen voor de ouder.

B(int x) : A(x) { }

of

B() : A(5) { }

Antwoord 5, autoriteit 2%

Hoe zit het met het gebruik van een sjabloonfunctie om alle constructors te binden?

template <class... T> Derived(T... t) : Base(t...) {}

Antwoord 6

De juiste code is

class A
{
    public: 
      explicit A(int x) {}
};
class B: public A
{
      public:
     B(int a):A(a){
          }
};
main()
{
    B *b = new B(5);
     delete b;
}

Fout is b/c Klasse B heeft geen parameterconstructor en ten tweede zou het een initialisatie van de basisklasse moeten hebben om de constructor van de parameterconstructor van de basisklasse aan te roepen


Antwoord 7

Hier is hoe ik ervoor kan zorgen dat de afgeleide klassen alle constructors van de ouder “erven”. Ik vind dit de meest rechttoe rechtaan manier, omdat het alle argumenten gewoon doorgeeft aan de constructor van de bovenliggende klasse.

class Derived : public Parent {
public:
  template <typename... Args>
  Derived(Args&&... args) : Parent(std::forward<Args>(args)...) 
  {
  }
};

Of als je een mooie macro wilt hebben:

#define PARENT_CONSTRUCTOR(DERIVED, PARENT)                    \
template<typename... Args>                                     \
DERIVED(Args&&... args) : PARENT(std::forward<Args>(args)...)
class Derived : public Parent
{
public:
  PARENT_CONSTRUCTOR(Derived, Parent)
  {
  }
};

Antwoord 8

afgeleide klasse erft alle leden (velden en methoden) van de basisklasse, maar afgeleide klasse kan de constructor van de basisklasse niet erven omdat de constructors niet de leden van de klasse zijn. In plaats van de constructors te erven door de afgeleide klasse, was het alleen toegestaan ​​om de constructor van de basisklasse aan te roepen

class A
{
    public: 
        explicit A(int x) {}
};
class B: public A
{
       B(int x):A(x);
};
int main(void)
{
    B *b = new B(5);
    delete b;
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes