This question already has answers here:
Does every object of virtual class have a pointer to vtable?
(9 answers)
Closed 6 years ago.
I've read a lot of posts and everyone says, that virtual table is per class, not per object and object only has _vtpr pointer to shared vtable. But please consider this example:
class Base
{
public:
virtual void func1(void) {}
virtual void func2(void) {}
private:
int dummy;
};
class Der1 : public Base
{
public:
virtual void func1(void) {}
private:
int dummy;
};
class Der2 : public Base
{
public:
virtual void func2(void) {}
private:
int dummy;
};
int main(void)
{
Base * obj1 = new Der1;
Base * obj2 = new Der2;
}
Does obj1 and obj2 relates to that one unique Base class vtable? I believe the answer is no, but can you please explain? And if both of these objects do relate to the same vtable, how it is determined which methods to be called? For example, obj1->func1 reference is different than obj2->func1.
UPDATE:
What operations are executed when doing Base * obj1 = new Der1;? Can someone write a pseudo code for these actions?
I hope the following illustration will help. Derived classes just copy the virtual table of base class, but they may modify the appropriate entry. The red part shows that given class has modified the entry in v-table. So, when instance of derived class is created, the modified table (specific to that class) is taken into consideration.
It is up to the compiler how duplicity of base class is handled (if base class has large number of functions - would derived have copy of entire virtual function table, and would modify the entries?).
IMO, compiler will simply copy entire table for each derived class to keep things simple. Searching appropriate method to call then becomes simple.
Related
I assume this is fairly basic, but I couldn't find any source here.
A derived class contains initialization information which needs to be passed to the base class. In this case it is a memory reservation.
class Derived: public Base
{
private:
const unsigned short memorySize= 100;
public:
inline Derived() : Base(memorySize) {}
void DoStuff();
};
This fails miserably. I expect the base constructor is called before the derived constructor, and memorySize is only assigned when the derived constructor is being called.
#define memorySize 100
class Derived: public Base
{
private:
public:
inline Derived() : Base(memorySize) {}
void DoStuff();
};
This works as expected.
My questions:
Is my assumption that memorySize in the first example has not yet been initialized at the time the base constructor is being called, or is something else happening here?
I have learned that #define for constants are undesirable in C++, and it's highly preferable to use const values. Is this an exception to this rule, or is there a more proper way to deal with this situation?
The two examples are entirely incomparable. In the first example, every instance of Derived gets its own copy of memorySize. As you guessed, the constructor of Derived takes care of that.
You don't want that at all. There's only one constant for the class, not a separate constant for every instance. That's written as
class Derived: public Base
{
private:
static const unsigned short memorySize = 100;
This question already has answers here:
multiple inheritance: unexpected result after cast from void * to 2nd base class
(3 answers)
Closed 8 years ago.
I have some codes like this:
#include <iostream>
using namespace std;
//base class
class Base
{
public:
Base(){}
virtual void f()
{
cout<<"father.f()"<<endl;
}
virtual ~Base(){}
};
//a empty class
class Base1
{
public:
Base1(){}
virtual ~Base1()
{
cout<<"~base1"<<endl;
}
};
//the child class of the base class
class Child :public Base
{
public:
Child(){}
virtual ~Child(){}
};
//the grandchild class of the base class,and child class of the base1 class
class Grand :public Base1,public Child
{
public:
Grand(){}
virtual ~Grand(){}
//overwrite base's f()
void f()
{
cout<<"grand.f"<<endl;
}
};
int main()
{
void *v = new Grand();
Base *b = (Base*)(v);
//i think it print "father.f()",but it print"~base1"
b->f();
return 0;
}
I run these code in code::blocks(version13.12),but it print "~base1",I don't konw why it don't print "father.f()"。I think the v point to the address of the grand's virtual table,so when i convert v to base and invoke the f function,then b invoke the first virtual function in the virtual table.
I do not know i'm right or wrong,can u tell me.Thank all of!
Because with multiple inheritance you can't cast directly to a upper class without passing by the child class. This because a void* doesn't contain any information about the layout in memory of the various classes that form your final Grand* instance.
To fix this you need indeed to cast it to it's runtime type:
Base *b = (Base*)(Grand*)v;
b->f();
Think about the fact that the layout could have Base in a different position. Think about another
class Grand2 : public Something, public Else, public Base1, public Child {
..
}
Now, where is Base located inside the Grand2 structure? In a different position compared to Grand. How could the compiler know the correct offset starting from just a pointer to a non specified class (which could be a Grand or a Grand2)?
This question already has answers here:
private inheritance
(6 answers)
Closed 9 years ago.
In C++: assume I have a class X. Is there any difference between private inheritance like this:
class Deriv : private X
{
public:
//constructor etc
void method()
{
usageOfMethodFromX();
}
};
and this:
class Deriv
{
private:
X * m_xinstance;
public:
//constructor etc
void method()
{
m_xinstance->usageOfMethodFromX();
}
};
Is there any difference that does not allow substitute private inheritance with having a member of derived class and vice versa? Is this the same?
Thanks!
There is a subtle difference in case your base class has a virtual function: even if the base class is inherited privately, it can be overridden:
#include <iostream>
class Base {
virtual int do_f() { return 1; }
public:
int f() { return this->do_f(); }
};
class Derived: Base {
int do_f() { return 2; }
public:
int g() { return this->f(); }
};
class Final: public Derived {
int do_f() { return 3; }
};
int main() {
Final final;
std::cout << final.g() << '\n';
}
The above code will print 3 (live example).
Another difference in your code is that the approach allocating memory, well, allocates memory on heap. You can avoid this heap allocation by embedding the object into your derived object.
There is a very significant and clear-cut difference: Consider this X:
class X {
protected:
void doSmth();
};
Only classes inheriting from X will have access to any and all protected members (here X::doSmth()).
Yes.
In the inheritance model, the lifetime of the two objects is intertwined. A number of methods are automatically connected by default (operator=, constructors, destructors) and others may be in the future (operator swap aka :=:, =default other operators like < or ==). On top of this, virtual method overriding and calling can route calls to pointers to your parent interface (which you can provide others, or can be invoked by calling your parent methods) back to you.
If you replace your X * m_xinstance with X m_xinstance things get closer to being the same. Lifetime is now tied, and many (all?) of the hooked up methods are now hooked up similarly. virtual behavior is also very different.
A final difference is that if your base class is empty, the empty base class optimization can occur in one case, but not the member instance. As different objects must have different addresses, a member of your class has a minimum size of 1, while an empty base class can take up zero memory.
I have the following structure
class Base
{
public:
Base(Type);
virtual render
}
class A
{
public:
Base(Type == A);
void render()
}
class B
{
public:
Base(Type == B);
void render()
}
void client_function()
{
Base baseObject(A);
//Base is an instance of class A
baseObject.render()//runs class A render
}
There are things in the above code that are not c++ as far as I am aware, they are closely related to pattern matching found in Haskell for example, but this is the best way I could find to illustrate my question without already knowing the answer ;)
In writing I want the client to be able to create a base object and pass the type of object as an argument, the correct specification of the object is returned and the client need not care less about it, just knows that running render will run the correct specific render.
Please feel free to ask questions if I have been unclear :)
I think you need to read about virtual functions and inheritance:
http://www.parashift.com/c++-faq-lite/virtual-functions.html
http://www.parashift.com/c++-faq-lite/proper-inheritance.html
http://www.parashift.com/c++-faq-lite/abcs.html
You need run-time polymorphism. There is not much important part of constructor. You have to inherit the Base into A and B. For example:
class Base
{
public:
virtual void render (); // <--- declare 'virtual'
virtual ~Base(); // <--- very much needed to avoid undefined behavior
};
class A : public Base //<---- inheritance
{
public:
void render(); // <--- this also becomes 'virtual'
};
...
Now you can use as per your requirement.
Base *baseObject = new A(); // <----- need to use pointer (or reference)
(*baseObject).render(); // <--- other way to write: baseObject->render();
delete baseObject;
I'm not sure I understood your question. In C++ you cannot choose your base class at runtime, but you certainly can have your base class depend from the derived class. This is done by using templates and what is known as the Curiously Recurring Template Pattern:
template <typename T> class Base {
public:
virtual void render(T *) {}
};
class A : public Base<A>
{
public:
void render(A * t) {}
};
class B : public Base<B>
{
public:
void render(B * t) {}
};
void client_function() {
A a1;
A a2;
a1.render(&a2); // calls A::render
a1.Base<A>::render(&a2); // calls Base<A>::render
Base<A> * ba = &a1;
ba->render(&a2); // calls A::render
}
Hope this answers your question.
What you ask for is exactly what inheritance is for: creating object from a class hierarchy that specializes a functionality.
In your example, apart from syntax problems, things will work as you expect, i.e. method A::render will be called, even if you don't know at compile time that object, declared as a Base, is indeed a A. That's virtual inheritance magicness.
class Base{
public:
void counter();
....
}
class Dervied: public Base{
public:
....
}
void main()
{
Base *ptr=new Derived;
ptr->counter();
}
To identify that the base class pointer is pointing to derived class and using a derived member function, we make use of "virtual".
Similarly, can we make derived data members "virtual"? (the data member is public)
virtual is a Function specifier...
From standard docs,
7.1.2 Function specifiers
Function-specifiers can be used only in function declarations.
function-specifier:
inline
virtual
explicit
So there is nothing called Virtual data member.
Hope it helps...
No, but you can create a virtual function to return a pointer to what you call virtual data member
No, in C++ there are no virtual data members.
I think not, but you might simulate it using virtual getters and setter perhaps?
To identify that the base class pointer is pointing to derived class and using a derived member function, we make use of "virtual".
That is not correct. We make virtual functions to allow derived classes to provide different implementation from what the base provides. It is not used to identify that the base class pointer is pointing to derived class.
Similarly, can we make derived data members "virtual"? (the data member is public)
Only non static member functions can be virtual. Data members can not be.
Here's a link with some more info on that
No, because that would break encapsulation in a myriad of unexpected ways. Whatever you want to achieve can be done with protected attributes and/or virtual functions.
Besides, virtual functions are a method of dispatch (i.e. selecting which function is going to be called), rather than selecting a memory location corresponding to the member attribute.
A class cannot have a virtual member, see for instance this answer.
However, you can have something similar using pointers, inheritance
and runtime polymorphism.
In the following snippet I define the prototype for a geometrical shape,
that has an area method. The picture class has a member shape* s;
and the methods of that shape pointed by s are used by picture::show().
In this setup it is undesirable to have an instance of picture before
an actual implementation of a shape has been given, hence we force picture to be
abstract by adding a dummy virtual function picture::make_real().
// prototypes
class shape
{
public:
virtual double area() = 0; // to be defined later
};
class picture
{
protected:
shape* s;
virtual void make_real() = 0; // force picture to be abstract
public:
picture(shape* ptr):
s{ptr}
{}
void show()
{
std::cout << s->area() << '\n';
}
};
Next, we actually implement a shape called square and a picture type
square_picture that (literally) has a square shape.
// actual implementation
class square : public shape
{
double len;
public:
square(double l):
len{l}
{}
double area() override
{
return len*len;
}
};
class square_picture : public picture
{
void make_real() override {} // square_picture is not abstract
public:
square_picture(double l):
picture{new square{l}}
{}
~square_picture()
{
delete s;
}
};
The class square_picture can be tested with the following snippet
int main()
{
square_picture A{2.0};
A.show();
//picture B{nullptr}; // error: picture is abstract
return 0;
}
which outputs:
4
I have a base class which uses an array of objects. From that class I derived a new class that uses an array of a different type of object. Both variables have exactly the same name. Virtual member functions were added to both classes to process the arrays. These member functions have no trouble finding the correct variable. The member functions and the variables they use are in a common scope.
The virtual member functions are nearly identical in both classes. Only the type of array changed.
C++ templates could have accomplished the same result.
Maybe you can see the problem in a equivalent way:
class VirtualDataMember{
public:
...
}
class DerviedDataMember: public VirtualDataMember{
public:
...
}
class Base{
public:
VirtualDataMember* dataMember;
void counter();
...
}