Interesting C++ Abstract Function - c++

why this is happen ?
When u create abstract class in c++ Ex: Class A (which has a pure virtual function)
after that class B is inherited from class A
And if class A has constructor called A()
suppose i created an Object of class B then the compiler initializes the base class first i.e.class A and then initialize the class B Then.......?
First thing is we can not access a constructor of any class without an Object then how it is initialize the constructor of abstract class if we can not create an object of abstract class .

Quick answer: constructors are special.
When the constructor of A is still running, then the object being constructed is not yet truly of type A. It's still being constructed. When the constructor finishes, it's now an A.
It's the same for the derived B. The constructor for A runs first. Now it's an A. Then the constructor for B starts running. During this, the object is still really an A. Only when B's constructor finishes does it become a B.
You can verify this by trying to call the pure virtual function from the constructors. If the function is defined in A, and B's constructor calls it, there will be a runtime error instead of running B's override, because the object is not of type B yet.
The compiler will not allow you to generate code that will construct an A, due to the pure virtual function. But it will generate code to construct an A as part of the process of constructing a B. There's no magic involved in this. The rule that you cannot construct an A is imposed by the language rules, not by physics. The language lifts that rule under the special circumstance of constructing objects of B.

class A is abstract but class B is not. In order to construct class B, it must implement all the pure virtual member functions of class A.
class A
{
public:
A() {}
virtual ~A() {}
virtual void foo() = 0; // pure virtual
int i;
};
class B : public A
{
public:
B() {}
virtual ~B() {}
virtual void foo() {}
int j;
};
The A class layout could be something like this:
+---------+ +---------+
| vftable | --> | ~A() | --> address of A::~A()
+---------+ +---------+
| i | | foo() | --> NULL, pure virtual
+---------+ +---------+
The B class layout could be something like this:
+---------+ +---------+
| vftable | --> | ~B() | --> address of B::~B()
+---------+ +---------+
| i | | foo() | --> address of B::foo()
+---------+ +---------+
| j |
+---------+

struct A {
A(int x) {..}
virtual void do() = 0;
};
struct B : public A {
B() : A(13) {} // <--- there you see how we give params to A c'tor
virtual void do() {..}
};

And if class A has constructor called A() suppose i created an
Object of class B then the compiler initializes the base class
first i.e.class A and then initialize the class B
Then.......?
Actually you have it the wrong way around:
When you create an object of class B the constructor of B is called.
If you do not specify how the B constructor calls A constructor then the compiler will automatically insert as the first action in the initializer list a call to the default constructor of A.
If you do not want to use the default constructor you must explicitly put the call to the appropriate A constructor as the first element in the initializer list.
When the construction of A is complete the construction of B will continue.
First thing is we can not access a constructor of any class without an Object
then how it is initialize the constructor of abstract class if we can not create
an object of abstract class .
You word the above as if you consider A and B different things. An object of class B is also an object of class A. It is the object as a whole that is valid. The whole object is of class B but this contains (as part of the same object) all the information that was from class A.

Just because you can't instantiate class A directly doesn't mean it's impossible to instantiate class A. You're not allowed to instantiate A because the compiler knows that A is abstract and rejects any code you write that attempts to directly instantiate A. It forbids code like this:
A a;
new A();
What makes a class abstract is that it has pure virtual methods. There is nothing inherently preventing such a class from being instantiated, though. The C++ standard simply says it's not allowed. The compiler is perfectly capable of generating instructions to instantiate an abstract class. All it has to do is reserve the right amount of memory and then invoke the constructor, the same as it would for a non-abstract class.
When you instantiate B, all the memory for the class gets allocated at once. Since all the bytes are there, there is essentially an A instance there, ready to be initialized by the constructor. (But note that the memory isn't formally considered an object of type A until after the A constructor has finished running.) The A constructor runs, and then the B constructor runs.

Related

Diamond inheritance with additional class copy constructor

So I was wondering lately what the copy constructor of an class will look if we have a base class A that is being virtually inherited by B and C, where B and C are inherited by D and D is inherited by E.
So I am a bit confused. Should D's copy constructor still have the base class's (A) constructor in its initializing list or is that the job of E now? Am I correct that E could inherit D non-virtually?
The implicitly generated copy constructor works fine, but if you wanted to explicitly write it yourself it could look like:
D(D const &o): A(o), B(o), C(o) {}
E(E const &o): A(o), D(o) {}
For initialization purposes, virtual base classes behave as if they are a direct base of the most-derived object. Any initializer in a subobject is ignored (e.g. in my code for E, the initialization D(o) actually does not initialize the A despite the fact that A is listed in D's copy constructor).
This is the same whether or not E inherits D virtually.
Link to further reading
Yes, A should still be in the initializing list and E does not need to inherit D virtually. The order of construction should be:
A() --> B() --> C() --> D()

Cannot access base class's protected constructor [duplicate]

One question about protected constructor. I learnt that the protected constructor can be used in the derived class. How ever, I found the code below has an error. Why does it happen like this?
class A
{
protected:
A(){}
};
class B: public A {
public:
B() {
A* f=new A(); // Why it is not working here
}
};
This has nothing to do with constructors specifically. This is just how protected access works.
The way protected access specifier works, it allows the derived class B to access the contents of an object of base class A only when that object of class A is a subobject of class B. That means that the only thing you can do in your code is to access the contents of A through B: you can access the members of A through a pointer of type B * (or a reference of type B &). But you cannot access the same members through a pointer of type A * (or reference A &).
Consider the following example
class A {
protected:
int i;
};
class B : A {
void foo() {
i = 0; // OK
this->i = 0; // OK
B *pb = this;
pb->i = 0; // OK
A *pa = this;
pa->i = 0; // ERROR
((A *) this)->i = 0; // ERROR
}
};
In the above B::foo, you can access base member A::i by using just plain i syntax. This is equivalent to using this->i syntax. Both will work, because the pointer this has type B *, i.e. you are accessing A::i thorough a pointer of type B *. This is exactly what the protected access specifier is supposed to allow. The access through pb pointer works for the very same reason.
However, when you "convert" this pointer to type A *, you can no longer access A::i through that new pointer, even though you are still trying to access they very same member as before.
When applied to constructors, the protected access specifier has a very specific effect: a protected constructor can only be used to initialize base-class subobjects. It cannot be used to initialize standalone objects (which is what you were trying to do). In other words, protected constructors are another way to implement the concept of abstract class in C++ (along with pure virtual methods). If the constructors of your class are protected, then your class is effectively abstract. You can't use it to define independent objects "from outside". (Of course, the above does not apply within friends, as well as within the class itself).
When a base class has a protected constructor, you can't instantiate the class directly. But you can do this to call the constructor from the base class constructor:
class A {
protected:
A() {}
};
class B: public A {
public:
B() : A() // allowed to access constructor like this
{
A* f = new A(); // Not allowed to access constructor like this!
}
};
A direct call to the constructor as shown below gives you the following error with gcc version 4.1.2:
A* f = new A(); // Not allowed to access constructor like this!
test.cpp:4: error: A::A() is protected
However, you this call to the constructor gives no errors:
B() : A() // allowed to access constructor like this
The reason behind this is that the second call accesses the A() constructor through inheritance, which is allowed. However, this tries to explicitly create a new instance of A() by calling the constructor directly:
A* f = new A(); // Not allowed to access constructor like this!
This might seem unintuitive, as B should be able to access A's constructor because B inherits from A. However, if you declare a constructor protected in C++, you can't create an instance of that class except through inheritance or a friend relationship.
Let me put my answer in steps:
1) Constructors don't get Inherited and that why in derived class, they can't be over ridden.
2) Constructors are invoked and not called.
3) If you have declared a simple function in A say protected void print() and then tried calling it in B, It would have worked. This happens bcoz, B has inherited this function.
4) When you do something like this b : a(), you are invoking the constructor and that's allowed.
5) Try making B a friend class of A and then run and see if it works.
Hope this helps.
I had the same question as this, and this link make me clear.
cppreference says like this:
Protected members form the interface for the derived classes (which is
distinct from the public interface of the class).
A protected member of a class Base can only be accessed
1) by the members and friends of Base
2) by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)

C++ Calling overwritten function in derived from base class

I have 2 classes, A and B and I need an overwritten function in B to be called from A's constructor. Here is what I have already:
class A {
A(char* str) {
this->foo();
}
virtual void foo(){}
}
class B : public A {
B(char* str) : A(str) {}
void foo(){
//stuff here isn't being called
}
}
How would I get code to be called in B::foo() from A::A()?
I need an overwritten function in B to be called from A's constructor
This design is not possible in C++: the order of construction of a B object is that first the base A sub-object is constructed, then B is constructed on top of it.
The consequence is that, while in A constructor, you are still constructing an A object: any virtual function called at this point will be the one for A. Only when the A construction is finished and the B construction starts, will the virtual functions of B become effective.
For achieveing what you want, you have to use a two step pattern: 1) you construct the object, 2) you initialize it.
I think you are referring to Calling Virtuals During Initialization Idiom (aka Dynamic Binding During Initialization), so please have a look here, where everything is explained:
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Calling_Virtuals_During_Initialization
https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctor-idiom
2nd site has very good explanation, but it's way longer than 1st.
In a constructor, the base class' function will get called, not the overridden version. The reason for this is that, using your example, B's initialization is not complete when A's constructor is called, and thus calling B's foo would be done with an incomplete B instance if this were otherwise allowed.

Why is protected constructor raising an error this this code?

One question about protected constructor. I learnt that the protected constructor can be used in the derived class. How ever, I found the code below has an error. Why does it happen like this?
class A
{
protected:
A(){}
};
class B: public A {
public:
B() {
A* f=new A(); // Why it is not working here
}
};
This has nothing to do with constructors specifically. This is just how protected access works.
The way protected access specifier works, it allows the derived class B to access the contents of an object of base class A only when that object of class A is a subobject of class B. That means that the only thing you can do in your code is to access the contents of A through B: you can access the members of A through a pointer of type B * (or a reference of type B &). But you cannot access the same members through a pointer of type A * (or reference A &).
Consider the following example
class A {
protected:
int i;
};
class B : A {
void foo() {
i = 0; // OK
this->i = 0; // OK
B *pb = this;
pb->i = 0; // OK
A *pa = this;
pa->i = 0; // ERROR
((A *) this)->i = 0; // ERROR
}
};
In the above B::foo, you can access base member A::i by using just plain i syntax. This is equivalent to using this->i syntax. Both will work, because the pointer this has type B *, i.e. you are accessing A::i thorough a pointer of type B *. This is exactly what the protected access specifier is supposed to allow. The access through pb pointer works for the very same reason.
However, when you "convert" this pointer to type A *, you can no longer access A::i through that new pointer, even though you are still trying to access they very same member as before.
When applied to constructors, the protected access specifier has a very specific effect: a protected constructor can only be used to initialize base-class subobjects. It cannot be used to initialize standalone objects (which is what you were trying to do). In other words, protected constructors are another way to implement the concept of abstract class in C++ (along with pure virtual methods). If the constructors of your class are protected, then your class is effectively abstract. You can't use it to define independent objects "from outside". (Of course, the above does not apply within friends, as well as within the class itself).
When a base class has a protected constructor, you can't instantiate the class directly. But you can do this to call the constructor from the base class constructor:
class A {
protected:
A() {}
};
class B: public A {
public:
B() : A() // allowed to access constructor like this
{
A* f = new A(); // Not allowed to access constructor like this!
}
};
A direct call to the constructor as shown below gives you the following error with gcc version 4.1.2:
A* f = new A(); // Not allowed to access constructor like this!
test.cpp:4: error: A::A() is protected
However, you this call to the constructor gives no errors:
B() : A() // allowed to access constructor like this
The reason behind this is that the second call accesses the A() constructor through inheritance, which is allowed. However, this tries to explicitly create a new instance of A() by calling the constructor directly:
A* f = new A(); // Not allowed to access constructor like this!
This might seem unintuitive, as B should be able to access A's constructor because B inherits from A. However, if you declare a constructor protected in C++, you can't create an instance of that class except through inheritance or a friend relationship.
Let me put my answer in steps:
1) Constructors don't get Inherited and that why in derived class, they can't be over ridden.
2) Constructors are invoked and not called.
3) If you have declared a simple function in A say protected void print() and then tried calling it in B, It would have worked. This happens bcoz, B has inherited this function.
4) When you do something like this b : a(), you are invoking the constructor and that's allowed.
5) Try making B a friend class of A and then run and see if it works.
Hope this helps.
I had the same question as this, and this link make me clear.
cppreference says like this:
Protected members form the interface for the derived classes (which is
distinct from the public interface of the class).
A protected member of a class Base can only be accessed
1) by the members and friends of Base
2) by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)

What's the difference between a derived object and a base object in c++?

What's the difference between a derived object and a base object in c++,
especially, when there is a virtual function in the class.
Does the derived object maintain additional tables to hold the pointers
to functions?
The derived object inherits all the data and member functions of the base class. Depending on the nature of the inheritance (public, private or protected), this will affect the visibility of these data and member functions to clients (users) of your class.
Say, you inherited B from A privately, like this:
class A
{
public:
void MyPublicFunction();
};
class B : private A
{
public:
void MyOtherPublicFunction();
};
Even though A has a public function, it won't be visible to users of B, so for example:
B* pB = new B();
pB->MyPublicFunction(); // This will not compile
pB->MyOtherPublicFunction(); // This is OK
Because of the private inheritance, all data and member functions of A, although available to the B class within the B class, will not be available to code that simply uses an instance of a B class.
If you used public inheritance, i.e.:
class B : public A
{
...
};
then all of A's data and members will be visible to users of the B class. This access is still restricted by A's original access modifiers, i.e. a private function in A will never be accessible to users of B (or, come to that, code for the B class itself). Also, B may redeclare functions of the same name as those in A, thus 'hiding' these functions from users of the B class.
As for virtual functions, that depends on whether A has virtual functions or not.
For example:
class A
{
public:
int MyFn() { return 42; }
};
class B : public A
{
public:
virtual int MyFn() { return 13; }
};
If you try to call MyFn() on a B object through a pointer of type A*, then the virtual function will not be called.
For example:
A* pB = new B();
pB->MyFn(); // Will return 42, because A::MyFn() is called.
but let's say we change A to this:
class A
{
public:
virtual void MyFn() { return 42; }
};
(Notice A now declares MyFn() as virtual)
then this results:
A* pB = new B();
pB->MyFn(); // Will return 13, because B::MyFn() is called.
Here, the B version of MyFn() is called because the class A has declared MyFn() as virtual, so the compiler knows that it must look up the function pointer in the object when calling MyFn() on an A object. Or an object it thinks it is an A, as in this case, even though we've created a B object.
So to your final question, where are the virtual functions stored?
This is compiler/system dependent, but the most common method used is that for an instance of a class that has any virtual functions (whether declared directly, or inherited from a base class), the first piece of data in such an object is a 'special' pointer. This special pointer points to a 'virtual function pointer table', or commonly shortened to 'vtable'.
The compiler creates vtables for every class it compiles that has virtual functions. So for our last example, the compiler will generate two vtables - one for class A and one for class B. There are single instances of these tables - the constructor for an object will set up the vtable-pointer in each newly created object to point to the correct vtable block.
Remember that the first piece of data in an object with virtual functions is this pointer to the vtable, so the compiler always knows how to find the vtable, given an object that needs to call a virtual function. All the compiler has to do is look at the first memory slot in any given object, and it has a pointer to the correct vtable for that object's class.
Our case is very simple - each vtable is one entry long, so they look like this:
vtable for A class:
+---------+--------------+
| 0: MyFn | -> A::MyFn() |
+---------+--------------+
vtable for B class:
+---------+--------------+
| 0: MyFn | -> B::MyFn() |
+---------+--------------+
Notice that for the vtable for the B class, the entry for MyFn has been overwritten with a pointer to B::MyFn() - this ensures that when we call the virtual function MyFn() even on an object pointer of type A*, the B version of MyFn() is correctly called, instead of the A::MyFn().
The '0' number is indicating the entry position in the table. In this simple case, we only have one entry in each vtable, so each entry is at index 0.
So, to call MyFn() on an object (either of type A or B), the compiler will generate some code like this:
pB->__vtable[0]();
(NB. this won't compile; it's just an explanation of the code the compiler will generate.)
To make it more obvious, let's say A declares another function, MyAFn(), which is virtual, which B does not over-ride/re-implement.
So the code would be:
class A
{
public:
virtual void MyAFn() { return 17; }
virtual void MyFn() { return 42; }
};
class B : public A
{
public:
virtual void MyFn() { return 13; }
};
then B will have the functions MyAFn() and MyFn() in its interface, and the vtables will now look like this:
vtable for A class:
+----------+---------------+
| 0: MyAFn | -> A::MyAFn() |
+----------+---------------+
| 1: MyFn | -> A::MyFn() |
+----------+---------------+
vtable for B class:
+----------+---------------+
| 0: MyAFn | -> A::MyAFn() |
+----------+---------------+
| 1: MyFn | -> B::MyFn() |
+----------+---------------+
So in this case, to call MyFn(), the compiler will generate code like this:
pB->__vtable[1]();
Because MyFn() is second in the table (and so at index 1).
Obviously, calling MyAFn() will cause code like this:
pB->__vtable[0]();
because MyAFn() is at index 0.
It should be emphasised that this is compiler-dependent, and iirc, the compiler is under no obligation to order the functions in the vtable in the order they are declared - it's just up to the compiler to make it all work under the hood.
In practice, this scheme is widely used, and function ordering in vtables is fairly deterministic, so ABI between code generated by different C++ compilers is maintained, and allows COM interoperation and similar mechanisms to work across boundaries of code generated by different compilers. This is in no way guaranteed.
Luckily, you'll never have to worry much about vtables, but it's definitely useful to get your mental model of what is going on to make sense and not store up any surprises for you in the future.
More theoretically, if you derive one class from another, you have a base class and a derived class. If you create an object of a derived class, you have a derived object. In C++, you can inherit from the same class multiple times. Consider:
struct A { };
struct B : A { };
struct C : A { };
struct D : B, C { };
D d;
In the d object, you have two A objects within each D objects, which are called "base-class sub-objects". If you try to convert D to A, then the compiler will tell you the conversion is ambiguous, because it doesn't know to which A object you want to convert:
A &a = d; // error: A object in B or A object in C?
Same goes if you name a non-static member of A: The compiler will tell you about an ambiguity. You can circumvent it in this case by converting to B or C first:
A &a = static_cast<B&>(d); // A object in B
The object d is called the "most derived object", because it's not a sub-object of another object of class type. To avoid the ambiguity above, you can inherit virtually
struct A { };
struct B : virtual A { };
struct C : virtual A { };
struct D : B, C { };
Now, there is only one subobject of type A, even though you have two subobject that this one object is contained in: subobject B and sub-object C. Converting a D object to A is now non-ambiguous, because conversion over both the B and the C path will yield the same A sub-object.
Here comes a complication of the above: Theoretically, even without looking at any implementation technique, either or both of the B and C sub-objects are now not contiguous anymore. Both contain the same A object, but both doesn't contain each other either. This means that one or both of those must be "split up" and merely reference the A object of the other, so that both B and C objects can have different addresses. In linear memory, this may look like (let's assume all objecs have size of 1 byte)
C: [1 byte [A: refer to 0xABC [B: 1byte [A: one byte at 0xABC]]]]
[CCCCCCC[ [BBBBBBBBBBCBCBCBCBCBCBCBCBCBCB]]]]
CB is what both the C and the B sub-object contains. Now, as you see, the C sub-object would be split up, and there is no way without, because B is not contained in C, and neither the other way around. The compiler, to access some member using code in a function of C, can't just use an offset, because the code in a function of C doesn't know whether it's contained as a sub-object, or - when it's not abstract - whether it's a most derived object and thus has the A object directly next to it.
a public colon. ( I told you C++ was nasty )
class base { }
class derived : public base { }
let's have:
class Base {
virtual void f();
};
class Derived : public Base {
void f();
}
without f being virtual (as implemented in pseudo "c"):
struct {
BaseAttributes;
} Base;
struct {
BaseAttributes;
DerivedAttributes;
} Derived;
with virtual functions:
struct {
vfptr = Base_vfptr,
BaseAttributes;
} Base;
struct {
vfptr = Derived_vfptr,
BaseAttributes;
DerivedAttributes;
} Derived;
struct {
&Base::f
} Base_vfptr
struct {
&Derived::f
} Base_vfptr
For multiple inheritance, things get more complicated :o)
Derived is Base, but Base is not a Derived
base- is the object you are deriving from.
derived - is the object the inherits his father's public (and protected) members.
a derived object can override (or in some cases must override) some of his father's methods, thus creating a different behavior
A base object is one from which others are derived. Typically it'll have some virtual methods (or even pure virtual) that subclasses can override to specialize.
A subclass of a base object is known as a derived object.
The derived object is derived from its base object(s).
Are you asking about the respective objects' representation in memory?
Both the base class and the derived class will have a table of pointers to their virtual functions. Depending on which functions have been overridden, the value of entries in that table will change.
If B adds more virtual functions that aren't in the base class, B's table of virtual methods will be larger (or there may be a separate table, depending on compiler implementation).
What's the difference between a derived object and a base object in c++,
A derived object can be used in place of a base object; it has all the members of the base object, and maybe some more of its own. So, given a function taking a reference (or pointer) to the base class:
void Function(Base &);
You can pass a reference to an instance of the derived class:
class Derived : public Base {};
Derived derived;
Function(derived);
especially, when there is a virtual function in the class.
If the derived class overrides a virtual function, then the overridden function will always be called on objects of that class, even through a reference to the base class.
class Base
{
public:
virtual void Virtual() {cout << "Base::Virtual" << endl;}
void NonVirtual() {cout << "Base::NonVirtual" << endl;}
};
class Derived : public Base
{
public:
virtual void Virtual() {cout << "Derived::Virtual" << endl;}
void NonVirtual() {cout << "Derived::NonVirtual" << endl;}
};
Derived derived;
Base &base = derived;
base.Virtual(); // prints "Derived::Virtual"
base.NonVirtual(); // prints "Base::NonVirtual"
derived.Virtual(); // prints "Derived::Virtual"
derived.NonVirtual();// prints "Derived::NonVirtual"
Does the derived object maintain additional tables to hold the pointers to functions?
Yes - both classes will contain a pointer to a table of virtual functions (known as a "vtable"), so that the correct function can be found at runtime. You can't access this directly, but it does affect the size and layout of the data in memory.