I know that it is not possible to have an instance of an abstract class as a base member of another class, i.e.,
#include <iostream>
class Base {
public:
Base() {};
virtual ~Base() {};
virtual int yield() = 0;
};
class C1: public Base {
public:
C1(): Base() {};
virtual ~C1() {};
virtual int yield() {return 1;};
};
class D {
public:
D(Base & b): b_(b) {};
virtual ~D() {};
private:
Base b_;
}
int main() {
C1 c;
D d(c);
}
will fail to compile with the error
test.cpp:22:10: error: cannot declare field ‘D::b_’ to be of abstract type ‘Base’
The obvious workaround is to use (shared) pointers instead. This, however, makes main somewhat more complicated to read,
int main() {
auto c = std::make_shared<C1>();
D d(c);
}
which I would really like to avoid.
Is there a way to keep the main file as simple as in the above example and still achieve the desired functionality?
You can't. When you are creating D it allocates (in heap or in stack) memory for B. And C1 class needs size of base class B plus size of extra variables/etc in C1 itself even if there are nothing new.
So, use pointers instead.
The error caused by virtual int yield() = 0;. If you use virtual int yield(), it will works. When you used virtual int yield() = 0;, it said that the function is a pure virtual function, so you must override it. So you should give its inheritance class and use the instance of inheritance class in class C1. In a world, virtual int yield() = 0; only remind you that it is only a interface, you must override it. I hope this can help you.
Since Base is an abstract class (has at least one pure virtual function), it can't be instantiated directly.
When you declare D's class member as "Base b_", you are effectively trying to create an instance. You can instead use a pointer there (or some kind of safe/smart pointer).
#include <iostream>
class Base {
public:
Base() {};
virtual ~Base() {};
virtual int yield() = 0;
};
class C1: public Base {
public:
C1(): Base() {};
virtual ~C1() {};
virtual int yield() {return 1;};
};
class D {
public:
D(Base * b): b_(b) {};
virtual ~D() {};
private:
Base *b_; // Use a pointer or safe ptr or something of that sort.
}
int main() {
C1 c;
D d(&c);
}
No. One of the properties of an abstract class is that it cannot be instantiated. That means an instance of an abstract class cannot be a member of another class.
Even if Base was not abstract, your class D's constructor would be slicing the object passed. If passed an instance of C1, the copying (in the initialiser list of D's constructor) would not magically cause an instance of D to contain an object of type C. It would instead create a copy only of the Base part of that object.
In short, your design is broken, and will not work even if - syntactically - it would be possible to simplify the code in main().
Related
Based on what I’ve read, it seems the memory for derived objects is made sequentially with the base class and all its data made first and then immediately followed by the following classes down the inheritance tree. So if I make a base class pointer that is equal to a new derived class object, and then increment it by one(which will actually add the size of the base class to the address), then will I arrive at the derived class? If so, can I then access the derived class’s data in this way?
Yes, and no. In the very simplest case it will work in most cases:
class Base {
public:
int v;
};
class Derived : public Base {
public:
int b;
};
int main() {
Derived d;
Base* p = &d;
p++;
// these will match on all compilers I'm aware of
printf("%p %p\n", p, &d.b);
return 0;
}
For single inheritance, that is typically what you'll see from most compilers (although I'd be very worried actually relying on that in production code!)
However, sadly things aren't always that simple! In C++ we often have multiple inheritance, virtual inheritance, abstract base classes and all those bits of goodness. So here is a scenario where it would absolutely not work!
struct Animal {
virtual ~Animal() = default;
virtual void Eat() {}
int a;
};
struct Mammal: Animal {
virtual void Breathe() {}
int b;
};
struct WingedAnimal: Animal {
virtual void Flap() {}
int c;
};
// A bat is a winged mammal
struct Bat: Mammal, WingedAnimal {
int d;
};
There are however far safer approaches to handling upcasting (e.g. dynamic_cast, or your own RTTI system). You probably will want to be using those :)
I have a base class which serves as an interface (if I use that word correctly). The idea is that the base class has some derived classes that implement one virtual function of the base class. Then I also need another class that extends the base class (lets call it extended base). What I would like is that I can store a class derived from base into an extended base pointer.
MWE:
class Base {
public:
virtual ~Base();
virtual double value();
}
class Derived : public Base{
public:
double value() override {return 5;}
}
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase ();
virtual double value2(){return 10;}
}
int main() {
ExtendedBase * object;
object = new Derived();
std::cout << object->value(); //should give implementation in Derived, i.e. 5
std::cout << object->value2(); //should give implementation in ExtendedBase, i.e. 10
delete object;
return 0;
}
With this MWE I get a compile error at the second line in the main. error: cannot convert 'Derived*' to 'ExtendedBase*' in assignment object = new Derived();. Part of me understands why it doesn't work (although I can't explain), but I would like to know if I can get the desired behaviour in some other way.
P.S. Sorry about the bad question name, I couldn't think of another way to keep it short
P.S.2 I know raw pointers like this are not advised. In the future I will change to smart pointers but I don't think they are needed for this simple example
ExtendedBase and Derived are each derived from Base. If you want to use an ExtendedBase* pointer to point to a Derived object, you will need to derive Derived from ExtendedBase.
To use a different example,
class Feline{
virtual void run();
}
class Housecat : Feline{
void run() {}
}
class BigCat : Feline{
virtual void run();
virtual void roar();
}
Here Feline, Housecat, and BigCat are analogous to Base, Derived, and ExtendedBase. BigCat and Housecat are each Feline, but since Housecat is not a BigCat, you can't use a BigCat* pointer to point to a Housecat.
This is the desired behavior from a language architect perspective.
For instance, if you have
class Ship
{
public:
virtual void move() = 0;
}
class Steamboat : public Ship
{
public:
virtual void move() override { ... }
}
class Sailboat : public Ship
{
public:
virtual void move() override { ... }
virtual void setSails() { ... }
}
Now, you don't want a Steamboat to become a Sailboat all of a sudden, hence:
Steamboat* tootoo = new Sailboat;
cannot be valid.
That's why your code cannot work. Conceptually.
So giving a quick fix is not possible, because your concept is not really clear.
When you are assigning an address to a pointer that means you should be able to access all the members of the type the pointer is pointing to through the pointer.
For ex,
class B {};
class D : B {};
B *p = new D();
now through p, at least you can access all the members of base portion of the derived class.
But in your code,
ExtendedBase * object;
object = new Derived();
object should be able to access all the members of ExtendedBase portion of the derived class. But how is it possible as derived class is not derived from ExtendeBase. So compiler is throwing error.
You need to do some changes in your code to work.
To make base as interface (abstract class), you need to define at
least one member function as pure virtual.
If you want to access the member function of ExtendedBase through
Base pointer, you should define same function 'val' in your
ExtendedBase.
Below are the changes.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {};
virtual double value() = 0;
};
class Derived : public Base{
public:
~Derived() {};
double value() {
return 5;
}
};
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase () {};
double value()
{
return 10;
}
};
int main() {
Base *p = new Derived();
std::cout << p->value() << std::endl;
delete p;
Base *p1 = new ExtendedBase();
std::cout << p1->value() << std::endl;
delete p1;
return 0;
}
I am new to OO programming and I was wondering how to solve the following question -
I have the following:
class A
{
public:
A() {};
~A() {};
virtual functionA() = 0;
}
class B: public A
{
public:
B() {};
~B() {};
functionA();
functionB();
}
Is there a way to access functionB using an object of the base class A? If no, why is it not possible? If yes, how does one do it? I tried to find this answer on this site but I didn't find anything concrete.
I would modify your example slightly to give you a better understanding:
class Animal
{
public:
A() {};
~A() {};
virtual Eat() = 0;
}
class Bird: public Animal
{
public:
B() {};
~B() {};
Eat();
Fly();
}
Should an Animal object be allowed to access the function Fly which belongs to Bird ?
No, because not all Animals are Birds.
But if you are sure than a specific Animal object is a Bird, then you can downcast the Animal object to Bird and then call Fly function.
However, this is not generally recommended. Upcasts (casting Bird to Animal) are okay because all Birds are Animals.
In general this is not possible. Class A can't access derived methods in Class B. The general relationship is upward for inheritance. Imagine a Class C that also has functionB, the resolution would be ambiguous.
class A
{
}
class B:public A
{
void functionB() {};
}
class C:public A
{
void functionB() {}
}
main()
{
A a;
a.functionB(); // What to call here?
}
With that being said, if an instance is in fact a B then a downcast could be used.
main()
{
B b;
A&a = b; // ok since a B is-a A
auto & b1 = dynamic_cast<B&>(a); // ok since this particular instance is-a B
b1.functionB();
}
perhaps this is what you were reaching for.
You can access only virtual method of B using the object A. This is called runtime-polymorphism and it is achieved with virtual function. Hence in order to implement the runtime behaviour C++ compiler inserts Virtual Table for every class having virtual function or class inherited from the class that has virtual function.
As in your code, i will make small modification:-
class A
{
public:
A() {};
~A() {};
virtual void functionA() = 0;
virtual void functionC();
}
class B: public A
{
public:
B() {};
~B() {};
void functionA() override; // C++ 11 : override keyword ensures that the function is virtual and is overriding a virtual function from a base class.
void functionB();
}
As the class A contains a virtual function C++ compiler inserts a pointer v_ptr called as virtual table pointer. Compiler also creates a table for that class called as virtual table known as vtable for the class. The table is created compile time v_ptr holds the address of v_table of the corresponding class. vtable is a array of function pointers pointing to virtual function. As functionA is pure virtual so in vtable the address entry for functionA will be null and but functionC has a valid address entry in vtable as it is not pure virtual function.
virtual table contains pointers to functionA() and functionC function of A class. But the implementation is incomplete as functionA is pure virtual. So you can't create object of class A.
As B Class inherits from A class, and as we know A class has a data member v_ptr. B class inherits v_ptr of A class but new virtual table will be created compile time for B class. Hence v_ptr of B class holds the address of vtable of B class. As B class has implemented functionA function. vtable of B class contains pointer to functionA function of B class but pointer to functionC function of base class i.e A class.
A *a = new B();
a->functionA(); //calls B functionA
a->functionC(); //calls A functionC since we haven't overriden this function in B
Let's say we have following code:
struct A{
virtual ~A(){}
void f(){
p = 42;
}
int p;
};
struct B : public virtual A{};
struct C : public virtual A{};
struct D : public B, public C, public A{}; //let's add non-virtual inheritance
int main(){
D* pA = new D();
pA->A::f(); //!
return 0;
}
Is there any way to set p to 42 in the most base class A?
Following construction pA->A::f(); sets p to 42 for non-virtual inherited class A. Can we do that without cast?
First off, there is no cast: you just qualify which version of A you want as there are more than one. Of course, the notation you have chosen actually doesn't work because it doesn't resolve the ambiguity in the first place. I guess you meant to use something like
pA->B::f();
If you don't want to put the burden of choosing which member function to call on the user of your class, you'll have to provide suitable forwarding functions for D e.g.:
void D::f() { this->B::f(); }
In C++, let's say I have a class Derived that implements an interface class BaseInterface, where BaseInterface has only pure virtual functions and a virtual destructor:
class BaseInterface
{
public:
virtual void doSomething() = 0;
~BaseInterface(){}
};
class Derived : public BaseInterface
{
public:
Derived() {}
~Derived(){}
protected:
virtual void doSomething();
private:
int x;
};
No classes outside the Derived class hierarchy should call Derived::doSomething() directly, i.e., it should only be accessed polymorphically through the BaseInterface class. To enforce this rule, I have made Derived::doSomething() protected. This works well, but I'm looking for opinions pro/con regarding this approach.
Thanks!
Ken
I think you're looking for the non-virtual interface (NVI) pattern: a public non-virtual interface that calls a protected or private virtual implementation:
class BaseInterface
{
public:
virtual ~BaseInterface(){}
void doSomething() { doSomethingImpl(); }
protected:
virtual void doSomethingImpl() = 0;
};
class Derived : public BaseInterface
{
public:
Derived() {}
virtual ~Derived(){}
protected:
virtual void doSomethingImpl();
private:
int x;
};
If it is part of the interface, why would you not want users to call it? Note that as it is, they can call it: static_cast<BaseInterface&>(o).doSomething() is just an awkward way of saying o.doSomething(). What is the point of using the interface... if the object fulfills the interface, then you should be able to use it, or am I missing something?
Since you are not actually blocking anyone from calling the methods, I don't see a point in making the code more complex (both the class and users of the class) for no particular reason. Note that this is completely different from the Non-Virtual Interface in that in this idiom virtual functions are not accessible publicly (at any level) while in your case, the intention is allowing access, and making it cumbersome.
What you are doing is also mentioned in standard ISO/IEC 14882:2003(E) 11.6.1 and believe you are correct. Other than the fact, the member function isn't pure virtual in the given example. It should hold for pure virtual functions too, AFAIK.
The access rules (clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.
[Example:
class B
{
public:
virtual int f();
};
class D : public B
{
private:
int f();
};
void f()
{
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK: B::f() is public,
// D::f() is invoked
pd->f(); // error: D::f() is private
}
—end example]
Access is checked at the call point using the type of the expression used to denote the
object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.
The key is the rest of your code. Only accept a BaseInterface* as an argument to any methods that require the doSomething() call. The client programmer is forced to derive from the interface to make his code compile.
This makes no sense to me. Regardless of which pointer you call doSomething(), you would still wind up with the method defined in most derived class. Consider the following scenario:
class BaseInterface
{
public:
virtual void doSomething() = 0;
~BaseInterface(){}
};
class Derived : public BaseInterface
{
public:
Derived() {}
~Derived(){}
virtual void doSomething(){}
private:
int x;
};
class SecondDerived : public Derived
{
public:
SecondDerived() {}
~SecondDerived(){}
private:
int x;
};
int main(int argc, char* argv[])
{
SecondDerived derived;
derived.doSomething(); //Derived::doSomething is called
BaseInterface* pInt = &derived;
pInt->doSomething(); //Derived::doSomething is called
return 0;
}