Inheritance in C++

ぐ巨炮叔叔 提交于 2019-12-24 15:33:07

问题


I was messing around with inheritance in C++ and wanted to know if anyone had any insight on the way it functions. Code below

#include <iostream>
using namespace std;

class AA {
 int aa;
 public:
 AA() {cout<<"AA born"<<endl;}
~AA(){cout<<"AA killed"<<endl;} 
virtual void print(){ cout<<"I am AA"<<endl;}
};

class BB : public AA{
 int bb;
 public:
 BB() {cout<<"BB born"<<endl;}
~BB() {cout<<"BB killed"<<endl;}
 void print() {cout<<"I am BB"<<endl;}
};

class CC: public BB{
 int cc;
 public:
 CC() {cout<<"CC born"<<endl;}
~CC(){cout<<"CC killed"<<endl;}
 void print() {cout<<"I am CC"<<endl;}
};


int main()
{
 AA a;
 BB b;
 CC c;
 a.print();
 b.print();
 c.print();     
 return 0;
}

so I understand that when you inherit something you inherit constructors and destructors. So when I do , "BB b" it prints "AA born". So the question I have

  1. Is an instance of AA created
  2. If yes, what is it called and how can I reference it?
  3. If no, why is the constructor being called

回答1:


Inheritance implements the "IS-A" relationship. Every BB is therefore also an AA.

You can see this in a number of ways, the easiest to demonstrate is:

BB b;
AA *aptr = &b;

Here your BB instance b is being pointed at by a pointer which only thinks of itself as pointing to an AA. If BB didn't inherit from AA then that wouldn't be legal.

The interesting thing is that when you call:

aptr->print();

It still prints "I am BB", despite the fact that the pointer you used is of type AA *. This happens because the print() method is virtual (i.e. polymorphic) and you're using a pointer. (The same would also happen with a reference too, but the type must be one of those for this behaviour to happen)




回答2:


  1. Is an instance of A created

Sort of. The BB b; code will allocate a BB instance. Part of that object is an AA.

  1. If yes, what is it called and how can I reference it?

Assuming the BB b; variable declaration, your part-of-BB AA instance is called b. If you want to call specific methods in AA that are hidden by BB methods, such as .print(), you need to invoke them like so:

BB b;
b.AA::print();



回答3:


BB is an instance of AA. You don't need to access anything special, because you already have that type.

When BB inherits from AA, here's how it's constructed.

  1. Call AA constructor
  2. Initialize member fields
  3. Call BB constructor

When destruction happens, this happens in reverse.

  1. Call BB destructor
  2. Destroy member fields (specific to BB)
  3. Call AA destructor

Oh, and you have at least one virtual function inside of AA. That means you need to make AA's destructor virtual (or bad things will happen).




回答4:


A class that derives from a base class contains that base class as a subclass, so an instance of the derived class contains a base subobject.

The subobject is constructed first. The constructor that is used for that is yours to determine: If you don't say anything, the default constructor is used; otherwise, the constructor that you specify in the base initializer list is called. Example:

struct Base
{
  Base() { }             // default constructor
  Base(int, double) { }  // some other constructor
  char q; 
};

struct A : Base
{
};

struct B : Base
{
  B() : A(12, 1.5) { }
};

Both A and B contain Base as a subclass. When you say A a;, the subobject's default constructor is called. When you say B b, the subobjects other constructor is called, because you said so.

As a consequence, if the base class has no accessible default constructor, then you must specify an accessible constructor explicitly.

You can reference members of the subobject by qualifying the name: a.Base::q or b.Base::q. If the name is unambiguous, that's the same as just a.q and b.q. However, when you deal with overridden or hidden member functions (and maybe multiple virtual inheritance), being able to specify the subobject explicitly may be useful or even necessary.




回答5:


In object-oriented languages, there are two main ways of creating objects that inherit from another one: concatenation and delegation. The first one is the most popular, the second is used in prototype-based languages.

Concatenation means that when B inherits from A, there are two parts in the object: in the first part of the object (of length equal to the size of A), the attributes (member variables/fields in C++) of A live. In the other part, there lives whatever attributes B adds to the object. Constructors for each involved class (A and B) are executed so all parts (all attributes) are initialized correctly.

Though the object is managed as a single unit, you can point it with a pointer of class A. In that case, the pointer only lets you see the first part, the part pertaining to class A (i.e. its attributes), but not the attributes from B, since the pointer can only see from the beginning to beginning + size of class A.

Say class A contains an integer x:

class A {
public: int x;
};

and B contains an integer y:

class B: public A {
public: int y;
} obB;

This means that an object of class B will have a length of 8 bytes (for 32 bits), the length of x plus the length of y, while the length of A is of only 4 bytes, the length of x. A pointer of class A to objB:

A * ptrA = &objB;

will only see x,

cout << ptrA->x << endl;
cout << ptrA->y << endl; // ERROR

while a pointer to B:

B * ptrB = &objB;

will be able to access both, x and y:

cout << ptrB->x << ',' << ptrB->y << endl;

In order to completely understand this, you need to know that ptrB->y is roughly translated into *( ( (int *) ptrB ) + 1 ), but that's another story.

Hope this helps.




回答6:


Inheritance in c++ means the ability of objects in one class to inherit properties of another class which implements the reusablity concept. This means that it is not necessary to create a new methods and just override the existing one, if required. Saves a lot of work.



来源:https://stackoverflow.com/questions/7506086/inheritance-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!