I'm getting a pointer to a base class (which is actually a pointer to some derived class). Then I want to call a function on that derived class, but I don't know which one it is.
class Base
{
};
class DerivedOne : public Base
{
public:
void functionA()
{ int x = 0; }
};
class DerivedTwo : public Base
{
public:
void functionA()
{ int x = 0; }
};
int main()
{
Base* derivedTwoPtr = new DerivedTwo();
reinterpret_cast<DerivedOne*>(derivedTwoPtr)->functionA();
return 0;
}
This works as I want, but I have to say it looks rather dodgy. Is it defined behavior? If not, is there a legal way to dynamically resolve this?
Hey, don't do that. That's what virtual methods are for.
class Base
{
public:
virtual void functionA()=0;
};
class DerivedOne : public Base
{
public:
virtual void functionA()
{ int x = 0; }
};
class DerivedTwo : public Base
{
public:
virtual void functionA()
{ int x = 0; }
};
int main()
{
Base* derivedTwoPtr = new DerivedTwo();
derivedTwoPtr->functionA();
return 0;
}
Just use virtual functions. That's what they are intended for. Your base class should look like
class Base
{
virtual void functionA() = 0;
};
where the = 0 bit is optional. If present the virtual function is known as a pure virtual function and enforces each subclass of Base to implement the function.
Now if you call functionA through a Base pointer you will get the method appropriate to whichever subclass the pointer really points to.
is there a legal way to dynamically
resolve this?
dynamic_cast can be used to cast to a specific derived class and invoke derived class methods. But in your case the best would be to provide a virtual method in Base class and provide different implementation for the virtual method in derived classes.
You basically answered your own question here:
Casting to one class and calling
function from sibling class?
This works as I want, but I have to
say it looks rather dodgy. Is it
defined behavior? If not, is there a
legal way to dynamically resolve this?
In short:
if (DerivedOne* one=dynamic_cast<DerivedOne*>(BasePtr))
one->functionA();
else if (DerivedTwo* two=dynamic_cast<DerivedTwo*>(BasePtr))
two->functionA();
But yeah, like vava said, don't do that.
Related
Is there any point to making virtual member functions, overridden from a base class private, if those are public in the base class?
struct base {
virtual void a();
};
struct derived : base {
// ...
private:
void a() override;
};
If you are forced to do a 2-phase construction on the implementation class (i.e. have an init() method as well as or instead of a constructor that has to be called (I know, but there are reasons), then this stops you calling any /other/ methods directly on the instance pointer before you pass it back as an interface pointer. Go the extra mile, make the inheritance private, and have your one public init function return the interface pointer!
Another reason is you just don't /need/ to write public: in a final implementation class declaration, so then by default everything is private. But why you would do that and use struct instead of class I don't know. Perhaps this was converted from class at some point due to a style war?
Looking at your design, I see one cannot call derived::a directly, but only through a base interface.
Is there any point? Consider that, once we have a derived instance, we can always up-cast to its base, so given
derived d;
while d.a() wouldn't compile, we can always do
base & b = d;
b.a(); //which actually calls derived::a
In other words: derived::a is not that private, after all, and I would discourage this design, which can be confusing to the user.
Things change if the members private in derived are private in base, as well: this time it is clear that they just cannot be called directly, outside base or derived.
Let's say we have a couple of functions, and want them to be called conditionally, according to a value passed as an argument to a third one:
struct base
{
void dosomething(bool x)
{
if(x)
{
do_this();
}
else
{
do_that();
}
}
private:
virtual void do_this(){}
virtual void do_that(){}
};
Thus a derived class could be like:
struct derived : base
{
private:
void do_this() override { }
void do_that() override { }
};
and no other class can call them, unless it extended base itself:
derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived
d.do_that() //won't compile
Yes, if you inherit the base class as private. Otherwise, it is more of a weird explicit-like restriction - user has to has to make an explicit conversion to use the function - it is generally ill advised as few will be able to comprehend the author's intention.
If you want to restrict some functions from base class, make a private/protected inheritance and via using keyword declare which base-methods you want to be protected/public in the derived class.
The same reasoning as for non-virtual methods applies: If only the class itself is supposed to call it make it private.
Consider the template method pattern:
struct base {
void foo() { a() ; b(); }
virtual void a() = 0;
virtual void b() = 0;
};
struct derived : base {
private:
void a() override {}
void b() override {}
};
int main()
{
derived().foo();
}
Perhaps a and b should have been protected, but anyhow the derived can change accesibility and it requires some documentation so that derived knows how it is supposed to implement a and b.
I have an abstract base class which declares a pure virtual function (virtual method() = 0;). Some of the inherited classes specialize and use this method but there's one of those inherited classes in which I don't want to make this method usable. How do I do it? Is making it private the only choice?
Well, you could throw that will make tacking where it is called easier.
void method() override { throw /* whatever */ ; }
Dynamic polymorphism is a runtime property. Hence a runtime error. If you look after something that will trigger at compile time, you need static polymorphism.
template<typename Child>
struct Parent {
void callMe() {
static_cast<Child*>(this)->callMeImpl();
}
};
struct SomeChild : Parent<SomeChild> {
};
Now, if you try to call callMe form the parent that is extended by SomeChild, it will be a compile time error.
You can also hold pointer to the parent just like dynamic polymorphism, as the parent will call the child function
Is making it private the only choice?
No, that's not a choice at all since you can still access the method if it's public or protected in the base classes.
Other than implementing the method in the class and resorting to run-time failures, there's not a lot you can do. You could port the whole thing to templates and use static polymorphism which, with further trickey, you could contrive a compile-time failure in certain instances, but that could be design overkill.
I guess you could make it a normal virtual function instead of a pure virtual function like this:
virtual void method() { /* code */ }
If this function is not being used in another class, you will be able to catch that. For example you could warn yourself:
virtual void method() { error = true; } //or whatever
As others have said there is no way of enforcing this at compile time. If you are referring to a pointer to a base class there is no way the compiler can know if that pointer is referring to one of the derived classes that does implement this method or one that doesn't.
So the case will have to be handled at runtime. One option is to just throw an exception. Another option is to introduce a level of indirection so that you can ask your base class if it implements a certain function before you call it.
Say you have a Base class with three methods foo, bar and doit and some derived classes do not want to implement foo then you could split up the Base class into two base classes:
class Base1 {
public:
virtual void foo() = 0;
};
class Base2 {
public:
virtual void bar() = 0;
virtual void doit() = 0;
};
Then in places where you are currently using Base you instead use a BaseSource:
class BaseSource {
public:
virtual Base1* getBase1() = 0;
virtual Base2* getBase2() = 0;
};
where getBase1 and getBase2 can return nullptr if a BaseSource does not offer that interface:
class Derived : public BaseSource, public Base2 {
public:
// don't implement foo();
// Implemementation of Base2
void bar() override;
void doit() override;
Base1* getBase1() override { return nullptr; } // Doesn't implement Base1
Base2* getBase2() override { return this; }
};
int main() {
std::vector<std::unique_ptr<BaseSource>> objects;
objects.push_back(std::make_unique<Derived>());
for (auto& o : objects) {
auto b1 = o->getBase1();
if (b1)
b1->foo();
auto b2 = o->getBase2();
if (b2)
b2->bar();
}
}
Live demo.
Class Base{
public:
...
void do_Something_base();
string identifier();
virtual void derived1_specific() {}; // nothing relevant to Base
virtual int derived2_specific(int) {};
};
Class Derived1:public Base {
public:
...
string identifier();
void derived1_specific();
};
Class Derived2:public Base {
public:
...
string identifier();
int derived2_specific();
};
int main() {
vector<Base*> owner;
/* push back some Derived1* & Derived2* to owner */
for (int i = 0; i < owner.size(); i++)
if (owner->identifier() == "d1")
owner->derived1_specific(int)
}
I have a larger program, that's the mechanics that make me confused. Should I write virtual function for every derived class? But this is very tedious.
I need to get and set some specific members, do some specific function in different child class. What is a smarter way or common way to do this?
thanks!
I would try really hard to find a common signature for the subclass-specific methods and then create one virtual function in the base class that can be called without some kind of ID-function.
Sometimes this can be achieved by passing some additional information needed for the subclass-specific function to the derived class's constructor, the common method could then be called e.g.
virtual void doClassSpecificStuff();
that uses member variables of your derived classes.
If you truly need differing return types etc, you might not want to inherit from a common ancestor OR not store all objects in the same container. Maybe composition works better than inheritance in your context (some class has-a specific worker object instead of is-a).
Edit: I erased the virtual solution since OP clarified that he needs to pass different parameters.
Since you have a way to know its actual type, there is nothing wrong in just casting to it, and then using it as that type:
Class Base{
public:
...
void do_Something_base();
string identifier();
};
Class Derived1:public Base {
public:
...
string identifier();
void TakeTwoInts(int x, int y);
};
Class Derived2:public Base {
public:
...
string identifier();
const char* ReturnAString();
};
int main() {
vector<Base*> owner;
/* push back some Derived1* & Derived2* to owner */
for (int i = 0; i < owner.size(); i++)
switch(owner[i]->identifier())
{
case "d1":
{
Derived1* d1 = static_cast<Derived1*>(owner[i]);
d1->TakeTwoInts(1,2);
break;
}
case "d2":
{
Derived2* d2 = static_cast<Derived2*>(owner[i]);
printf("%s",d2->ReturnAString());
break;
}
...
}
}
}
If you're not sure if the conversion is possible, use dynamic_cast instead: it returns a clean nullptr, rather than garbage, if the cast you ask is impossible.
By the way, note that the identifier() functions in the derived classes will never be called. Either you store the id in a variable accessible from Base, and then you don't need the function in each derived class, or you have to make identifier() a virtual function.
There are no :
virtual std::string Base::identifier()
In this case, when you have a Base* you cant call identifier() on it
You'll have to forgive me if this is a really basic question; I haven't used C++ this much in a long time so I've forgotten how a lot of it works.
Anyway, I have a base class and a couple derived classes like this (super oversimplified, but the gist is the same):
class Base
{
public:
Base () { }
int SomeFunction (int x, int y); // abstract definition
};
class Derived1 : public Base
{
public:
Derived1() : Base() { }
int SomeFunction (int x, int y)
{
// actual implementation
return 4;
}
};
class Derived2 : public Base
{
public:
Derived2() : Base() { }
int SomeFunction (int x, int y)
{
// actual implementation
return 7;
}
};
Later on in main I have a list of Base objects:
Base *baseobjects[10];
Later I fill that array with instances of Derived1 and Derived2. That works with baseobjects[i] = &newDerived1 (where newDerived1 is an instance of the Derived1 class). That's all fine.
What I can't seem to figure out is how to later iterate through the baseobjects array and call SomeFunction on every instance in the list without explicitly knowing which derived class I'm using. I've done this in C# and it works fine, but apparently my C++ syntax is off:
int result = baseobjects[i]->SomeFunction(a, b);
That gives me a LNK2019 error when I try to compile, apparently because it's looking at the Base class for the implementation and it isn't there. I'm assuming I have to use some pointer tricks to get it to look at the proper derived method, but nothing I've tried yet has worked. Any suggestions?
Your method should be declared virtual. And in your case, probably pure virtual.
class Base
{
public:
Base () { }
virtual int SomeFunction (int x, int y) = 0; // abstract definition
};
Note that, while this is not absolutely required, you might as well declare a virtual destructor. Do it if you ever delete a derived instance trough a pointer of the base class.
class Base
{
public:
//Base () {} // This is not required, the default provided constructor is similar.
virtual ~Base() {} // virtual destructor.
virtual int SomeFunction (int x, int y) = 0; // abstract definition
};
Edit:
Also, regarding the link error you posted:
Either you forgot the = 0, either you are calling Base::SomeFunction() from somewhere.
As Thomas Edleson points out, = 0 does not mean that your function has no implementation: it can have one, but it only requires the derived classes to (re)implement it to not being abstract.
If you are interested in this topic, I suggest you read this post.
If you want to override a method, it must be virtual.
class Base
{
public:
Base () { }
virtual int SomeFunction (int x, int y); // abstract definition
}
Seccond thing is that your derivated classes did not extends of your base-class.
class Derived1 : public Base
{
public:
Derived1() : Base() { }
int SomeFunction (int x, int y)
{
// actual implementation
return 4;
}
}
You have to declare the member function SomeFunction()
virtual
abstract
So the declaration for Base should look like this:
class Base
{
public:
Base() { }
virtual int SomeFunction(int x, int y) = 0;
};
You can omit the virtual keyword in the derived classes.
To just slightly elaborate on ereOn's answer, you do need to declare you base class function (ie: your abstract definition) in order for your derived classes to be able to override it. What he didn't clarify though is that other than that, what you've posted is fine (that is, the calls to the function you posted will then work without any modification).
Note also, that if you're after a pure abstract definition, you should append = 0 to your function declaration as follows:
class Base
{
public:
Base () { }
virtual int SomeFunction (int x, int y) = 0; // pure abstract definition
};
This lets the compiler know that classes derived from Base must supply their own implementation of SomeFunction.
I'm slightly confused about runtime polymorphism. Correct me if I am wrong, but to my knowledge, runtime polymorphism means that function definitions will get resolved at runtime.
Take this example:
class a
{
a();
~a();
void baseclass();
}
class b: class a
{
b();
~b();
void derivedclass1();
}
class c: class a
{
c();
~c();
void derivedclass2();
}
Calling methodology:
b derived1;
a *baseptr = &derived1; //here base pointer knows that i'm pointing to derived class b.
baseptr->derivedclass1();
In the above calling methodology, the base class knows that it's pointing to derived class b.
So where does the ambiguity exist?
In what cases will the function definitions get resolved at runtime?
This code, at run time, calls the correct version of f() depending on the type of object (A or B) that was actually created - no "ambiguity". The type cannot be known at compile-time, because it is selected randomly at run-time.
struct A {
virtual ~A() {}
virtual void f() {}
};
struct B : public A {
virtual void f() {}
};
int main() {
A * a = 0;
if ( rand() % 2 ) {
a = new A;
}
else {
a = new B;
}
a->f(); // calls correct f()
delete a;
}
There is no ambiguity exists in the example provided.
If the base class has the same function name as the derived class, and if you call in the way you specified, it will call the base class's function instead of the derived class one.
In such cases, you can use the virtual keyword, to ensure that the function gets called from the object that it is currently being pointed. It is resolved during the run time.
Here you can find more explanation..
Turn this
void baseclass();
to
virtual void baseclass();
Override this in your Derived classes b and c. Then
b *derived1 = new derived1 ();
a *baseptr = derived1; //base pointer pointing to derived class b.
baseptr->baseclass();
will invoke derived1 definition, expressing run time polymorphism. And do remember about making your destructor virtual in Base. Some basic reading material for polymorphism
Runtime means that exact method will be known only at run time. Consider this example:
class BaseClass
{
public:
virtual void method() {...};
};
class DerivedClassA : public BaseClass
{
virtual void method() {...};
};
class DerivedClassB : public BaseClass
{
virtual void method() {...};
};
void func(BaseClass* a)
{
a->method();
}
When you implement your ::func() you don't know exactly type of instance pointed by BaseClass* a. It might be DerivedClassA or DerivedClassB instance etc.
You should realize, that runtime polymorphism requires special support from language (and maybe some overhead for calling "virtual" functions). In C++ you "request" for dynamic polymorphism by declaring methods of base class "virtual" and using public inheritance.
You need to have some useful business method declared in the base and in each derived class. Then you have code such as
a->someMethod();
Now the a pointer might point to an instance of any of the derived classes, and so the type of what a is pointing to must determine which someMethod() is called.
Lets have an experiment
#include <iostream>
using namespace std;
class aBaseClass
{
public:
void testFunction(){cout<<"hello base";}///Not declared as virtual!!!!
};
class aDerivedClass:public aBaseClass
{
public:
void testFunction(){cout<<"hello derived one";}
};
class anotherDerivedClass:public aDerivedClass
{
public:
void testFunction(){cout<<"hello derived two";}
};
int main()
{
aBaseClass *aBaseClassPointer;
aBaseClassPointer=new aDerivedClass;
aBaseClassPointer->testFunction();
}
The above code does not support run time polymorphism. Lets run and analyze it.
The output is
hello base
Just change the line void testFunction(){cout<<"hello base";} to virtual void testFunction(){cout<<"hello base";} in aBaseClass. Run and analyze it. We see that runtime polymorphism is achieved. The calling of appropriate function is determined at run time.
Again change the line aBaseClassPointer=new aDerivedClass to aBaseClassPointer=new anotherDerivedClass in main function and see the output. Thus the appropriate function calling is determined at run time (when the program is running).