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;
}
Related
class Base1{
public:
Base1(){};
virtual ~Base1() = 0;
}
class Derived1 : public Base1{
public:
Derived1(int a) : a(a){};
~Derived1();
int a;
}
class Base2{
public:
Base2(){};
virtual ~Base2() = 0;
}
class Derived2 : public Base2{
public:
Derived2(int b) : b(b){};
~Derived2();
int b;
void func(const Base1 &base1); // How to access Derived1::a here?
}
Given the above class definition, how can I access Derived1::a in void func(const Base1 &base1)? I am still new to polymorphism. I tried to use different static_cast or dynamic_cast methods but none of them works. What should I do inside the function so I can access a derived class member from a base class reference?
FYI I can't change the class definition for my coursework requirement, and that is what given to me. I understand that it is simpler to just pass Derived1 as parameter but I am not allow to do so.
Given the above class definition, how can I access Derived1::a in void func(const Base1 &base1)? ... FYI I can't change the class definition for my coursework requirement, and that is what given to me.
Ideally, you should expose a virtual method in Base1 that returns an int (or int&), and then have Derived1 override that method to return its a member.
But, given that you are not allowed to change the class definitions, that is not an option.
You need a pointer or reference to a Derived1 object in order to access its a member directly. Which really leaves you with only 1 choice - you can use dynamic_cast to typecast the base class reference to the derived class type, eg:
void Derived2::func(const Base1 &base1)
{
// this will raise an exception if the cast fails at runtime
const Derived1 &d = dynamic_cast<const Derived1&>(base1);
// use d.a as needed...
}
Alternatively:
void Derived2::func(const Base1 &base1)
{
// this will return null if the cast fails at runtime
const Derived1 *d = dynamic_cast<const Derived1*>(&base1);
if (d) {
// use d->a as needed...
} else {
// do something else...
}
}
If I inherit a derived class privately from a base class, I cannot get the polymorphism of the inhritetted class.
But I can get the polymorphism of 'this' pointer inside the derived class.
I'm very curious about why 'this' pointer is allowed to polymorphism to its private parent, however, a pointer outside of the class is not.
Thanks in advance!
#include <iostream>
class Shape
{
public:
virtual void say() const = 0;
virtual void who()
{
std::cout << "Shape" << std::endl;
}
void whoAmI() {
this->who();
}
};
class Squire : private Shape
{
public:
virtual void say() const
{
std::cout << "Squire" << std::endl;
}
void doSay()
{
// why this pointer to Shape type is allowed in class?
privateSay(this);
}
private:
void privateSay(Shape* s)
{
s->say();
}
};
void say(Shape* s)
{
s->say();
}
int main(int argc, const char * argv[]) {
// insert code here...
Squire* s = new Squire();
// allowed
s->doSay();
// not allowd, compile errors
// Cannot cast 'Squire' to its private base class 'Shape'
say(s);
return 0;
}
=========
Edit to clarify.
Thanks for all the answers.
To clarify my question, I think if C++ allows this behavior, mybe it violates the encapsulation a little.
A clearer case:
#include <iostream>
class Base
{
public:
void baseFunc() const
{
std::cout << "baseFunc" << std::endl;
}
};
class Worker
{
public:
Worker(Base *pBase)
{
base_ = pBase;
}
void breakFunc() const
{
base_->baseFunc();
}
private:
Base *base_;
};
class Derived : private Base
{
public:
void init()
{
worker_ = new Worker(this);
}
Worker* getWorker()
{
return worker_;
}
private:
Worker *worker_;
};
int main()
{
Derived derived;
derived.init();
Worker *worker = derived.getWorker();
worker->breakFunc();
}
The object of Base class only exisits in the object of Derived class as the parent object part, however, the Derived class inheritents Base class privately, which means the object of the Derived class has-an object of the Base class, privately.
The code above violates the encapsulation rule of the Derived class, however, even no warnning is given during compilation.
In my opinion, an explicit cast should be used under the circumstances,or an warning should be given during compilation.
The question asked here is why a base class is accessible when privately inherited.
The answer is rather simple: Because base classes are always visible to inherited regardless of the type of inheritance.
You can static_cast to a base class when the base is visible within the context.
class base
{
};
class inherited : base
{
public:
void foo()
{
// works, base is visible within the method.
auto pBase = static_cast<base*>(this);
}
};
int main() {
inherited i{};
// auto pBase = static_cast<base*>(&i); // won't compile, base is not visible
return 0;
}
Private inheritance means that both public and protected symbols from the base class become private symbols of the derived class. private symbols of the base class are inaccessible to the derived class. With exception of private virtual methods which can still be overridden.
this pointers, or in general Class* ptr used inside the class, can access private fields of the class.
Since the symbol Shape::say is public in Shape, it becomes private in Squire(BTW Did you mean Square?). This prevents its usage by public but not by this. Due to rules of virtuals, this "privatizes" the whole chain of overridden methods.
void Squire::privateSay(Shape* s)
{
// Works because `Shape::say` is a public symbol of Shape -> private symbol of Squire and `this` can access private symbols.
s->say();
}
void say(Shape* s)
{
// Shape::say is a private symbol, obviously cannot be called.
s->say();
}
If there existed private Shape::foo() method, it would not be accessible even through this in any of the Squire's methods.
I need to copy an object of a polymorphic class having a base pointer. I know that I can implement a virtual method for this. But what if the base class should not be abstract? Leaving the method without pure-specifier can lead to run-time bugs, if you forget reimplement it in the derived. It's uncomfortable. What is the best way to handle this?
There are good reasons why you should never want to instantiate a base class.
If you do need to make a empty final class use the following.
class IBase
{
virtual void SharedCode()
{
1 + 1;
/// code here
};
virtual void AbstractDecalration() = 0;
};
class Base final: IBase
{
void AbstractDecalration() override;
};
Base b{};
All Future Derived classes will be able to use the SharedCode of IBase and you will have a Instantiated class of Base that is final. This is for future proofing your code base.
However I realize that is not the question you asked so here is a implementation were I use a simple check to the vtable pointer of the class to see if I have the correct class.
This is a runtime check and doesn't work across libraries use dynamic_assert if that is the case.
#include <memory>
#include <type_traits>
#include <assert.h>
class Base {
public:
auto clone() const
{
return std::unique_ptr<Base>(this->clone_impl());
}
private:
virtual Base* clone_impl() const
{
Base b{};
int* bVtablePtr = (int*)((int*)&b)[0];
int* thisVtablePtr = (int*)((int*)this)[0];
assert(bVtablePtr == thisVtablePtr);
return new Base(*this);
}
};
class Derived : public Base
{
auto clone() const
{
return std::unique_ptr<Derived>(this->clone_impl());
}
virtual Derived* clone_impl() const
{
return new Derived();
}
};
class Falty : public Base{};
int main(){
std::unique_ptr<Derived> good(new Derived());
std::unique_ptr<Falty> falty(new Falty());
good->clone(); // oke
falty->clone(); // this function asserts at runtime
}
Note the private clone_impl and public unique_ptr retuning clone method.
Very usefull to prevent memory leaks in your code
You can achieve what you want by introducing another abstract base class plus using CRPT for clone function. Then, clone will be automatically implemented in all derived classes "for free" (without manual retyping). Example:
struct Abstract
{
virtual ~Abstract() {}
virtual Abstract* clone() const = 0;
virtual void say() const = 0;
};
template <typename B, typename D>
struct AbstractCloneable : B
{
virtual B* clone() const override
{
return new D(static_cast<const D&>(*this));
}
};
// original base class
struct Base : AbstractCloneable<Abstract, Base>
{
virtual void say() const override
{
std::cout << "Base" << std::endl;
}
};
// original derived class #1
struct Derived1 : AbstractCloneable<Base, Derived1>
{
virtual void say() const override
{
std::cout << "Derived1" << std::endl;
}
};
And a test program:
int main()
{
std::unique_ptr<Abstract> ptr1 = std::make_unique<Base>();
ptr1->say();
std::unique_ptr<Abstract> ptr1_copy{ ptr1->clone() };
ptr1_copy->say();
std::unique_ptr<Abstract> ptr2 = std::make_unique<Derived1>();
ptr2->say();
std::unique_ptr<Abstract> ptr2_copy{ ptr2->clone() };
ptr2_copy->say();
}
Which outputs:
Base
Base
Derived1
Derived1
Live demo: https://godbolt.org/z/3FeSTd
See this article for more details and explanations: C++: Polymorphic cloning and the CRTP (Curiously Recurring Template Pattern).
I spent a lot of time trying to figure out why my code displays "Derived3" after I run it and I cannot understand it at all. From what I have read here on many posts, dynamic_cast should somehow say whether a pointer (in this case b) is (in this case) Derived2 or not. However, it passed the condition and when it should print out the display() function from Derived2 class, it strangely displayes the one from the Derived3 class. I am just wondering why the program displays "Derived 3" instead of not showing anything, since b pointer is clearly not pointing to a Derived2 object.
#include <iostream>
using namespace std;
class Base
{
int b;
public:
virtual void display()
{
cout<<"Base"<<endl;
}
};
class Derived: virtual public Base{
public:
void display()
{
cout<<"Derived"<<endl;
}
};
class Derived2: virtual public Base{
public:
void display()
{
cout<<"Derived 2"<<endl;
}
};
class Derived3:public Derived,public Derived2{
public:
void display()
{
cout<<"Derived 3"<<endl;
}
};
int main()
{
Base *b = new Derived3();
Derived2 *aux = dynamic_cast<Derived2*>(b);
if(aux)
{
aux->display();
}
return 0;
}
However, after editing the code a little bit, it works as it should be.
#include <iostream>
using namespace std;
class Base
{
int b;
public:
virtual void display()
{
cout<<"Base"<<endl;
}
};
class Derived: public Base{
public:
void display()
{
cout<<"Derived"<<endl;
}
};
class Derived2: public Base{
public:
void display()
{
cout<<"Derived 2"<<endl;
}
};
class Derived3:public Base{
public:
void display()
{
cout<<"Derived 3"<<endl;
}
};
int main()
{
Base *b = new Derived3();
Derived2 *aux = dynamic_cast<Derived2*>(b);
if(aux)
{
aux->display();
}
return 0;
}
Inheritance is a "Is-a" relationship.
Every Derived is both a Derived and a Base. By that pattern, every Derived3 is a Derived3, a Derived2, a Derived and a Base at the same time.
It would thus not make sense for that cast to fail.
The output is then finally the result of a normal virtual function call on a Derived2*. This is no different than in the most trivial example of inheritance, like in this snippet:
#include <iostream>
struct A {
virtual void fun() const {
std::cout << 'A';
}
};
struct B : A {
void fun() const {
std::cout << 'B';
}
};
int main () {
const A &a = B();
a.fun(); // prints 'B'
}
If you have a pointer or reference to some base class, a virtual function call will resolve to the actual type of the object it is called on. In your case, that's a Derived2* pointing to a child-class of type Derived3, so the function is looked up in the latter.
Keep in mind that the dynamic_cast only changes the type of the pointer, not the type of the object it points to!
However, it passed the condition and when it should print out the display() function from Derived2 class, it strangely displayes the one from the Derived3 class.
That's because of dynamic dispatch. Remember that display() is declared to be a virtual member function. It continues to be a virtual member function for all the derived classes.
Even though you cast the pointer from Base* to Derived*, the underlying object is still a Derived3. Hence, the dynamic dispatch mechanism calls Derived3::display().
Derived3::display() will also be called if you use:
Base *b = new Derived3();
b->display();
I have following
class base
{
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};
now I have
base* pbase = new derived();
pbase->myFunc();
I am getting error myFunc is not a member function of base.
How to avoid this? and how to make myFunc get called?
Note I should have base class contain no function as it is part of design and above code is part of big function
If you are adamant that this function should NOT be a part of base, you have but 2 options to do it.
Either use a pointer to derived class
derived* pDerived = new derived();
pDerived->myFunc();
Or (uglier & vehemently discouraged) static_cast the pointer up to derived class type and then call the function
NOTE: To be used with caution. Only use when you are SURE of the type of the pointer you are casting, i.e. you are sure that pbase is a derived or a type derived from derived. In this particular case its ok, but im guessing this is only an example of the actual code.
base* pbase = new derived();
static_cast<derived*>(pbase)->myFunc();
myfunc needs to be accessible from the base class, so you would have to declare a public virtual myfunc in base. You could make it pure virtual if you intend for base to be an abstract base class, i.e one that cannot be instantiated and acts as an interface:
class base
{
public:
virtual void myfunc() = 0; // pure virtual method
};
If you ant to be able to instantiate base objects then you would have to provide an implementation for myfunc:
class base
{
public:
virtual void myfunc() {}; // virtual method with empty implementation
};
There is no other clean way to do this if you want to access the function from a pointer to a base class. The safetest option is to use a dynamic_cast
base* pbase = new derived;
....
derived* pderived = dynamic_cast<derived*>(pbase);
if (derived) {
// do something
} else {
// error
}
To use the base class pointer, you must change the base class definition to be:
class base
{
public:
virtual void myFunc() { }
};
I see no other way around it. Sorry.
You could add it as a member of base and make it a virtual or pure virtual function. If using this route however, you should also add a virtual destructor in the base class to allow successful destruction of inherited objects.
class base
{
public:
virtual ~base(){};
virtual void myFunc() = 0;
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};