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.
Related
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
Please look at this code. It just reflects basic concept of what I want to do:
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
/* Some code I want to reuse */
Redefined();
}
virtual ~Base() {}
void Redefined() { val = 10; }
int val;
};
class Derived : public Base
{
public:
Derived() : Base() {}
~Derived() {}
void Redefined() { val = 25; }
};
int main()
{
Base* check = new Derived();
cout << check->val << endl;
system("pause");
return 0;
}
I want the val property of check object to be 25 instead of 10.
As you can see I have two classes. Base class constructor have some complex functionality, which I want Derived class to have in it's constructor as well. How can I change derived function Redefined so that I won't have to rewrite Derived constructor completely (in fact just copy-pasting the whole base class constructor code and replacing one single line of code - updated version of Redefined function)?
You can't really override a function that way. Normally you could use a virtual functions, but that doesn't work the way you want in the constructor.
A better way is to pass the value you want to the Base constructor:
class Base
{
public:
Base(int init_val = 10)
{
/* Some code I want to reuse */
val = init_val;
}
virtual ~Base() {}
int val;
};
class Derived : public Base
{
public:
Derived() : Base(25) {}
~Derived() {}
};
That way any derived class can pass its choice of value to the base class.
Based on comments above:
I would actually think that the correct solution is to have a "interface" type baseclass (that is, a baseclass with pure virtual functions, and the derived class actually implements the correct behaviour), and then let each class deal with constructing its own DirectX buffers. You may find that you need, say, 2-3 different derived classes that construct buffers in different ways, and then derive from those the classes that actually do the real work. I hope that makes sense.
Alternatively, you would be passing enough parameters to the base-class, such that the buffers can be constructed. But I think the first suggestion is a better choice.
EDIT:
I have no updated the question, whilst doing so I realized the scope of the question has completely changed, so I apologize for this. I am dealing with Threads so that static function has to be there. I have tried to abstract the Threading stuff out of the question as much as possible.
I am getting a pure virtual function call error, so I thought maybe I have the implementation wrong. Here is what I have:
class Base
{
protected:
virtual int f(void) = 0;
static void baseFunction(void* param);
};
static void Base::baseFunction (void* param)
{
Base *parent = (Base*) parameter;
int i = parent->f();
}
class Derived : public Base
{
private:
int _memeber;
int f(void);
};
int Derived::f(void)
{
_member = 0;
cout << "Derived _memeber is: " << _member << endl;
return 0;
}
void main ()
{
Derived d;
d.baseFunction(d);
}
I need the function Derived::f(void) to have access to the Derived class members.
The definition looks fine, but I will hazard a guess that you're calling the virtual function from the constructor or destructor of Base. In that case, virtual dispatch is done as if the dynamic type were Base, not Derived, and if the function is pure virtual then you get undefined behaviour.
UPDATE: You also say "I am dealing with threads". In that case, it's possible that a data race could cause one thread to call the function while another is still constructing the object - again, giving undefined behaviour. You need to make sure all data accesses are correctly synchronised.
It's OK, just missing semicolons after the class declarations.
Add return type to the Derived method. Also add semicolons after class definitions
You are missing the return type for f and ; after class definitions
Change your code to
class Base
{
protected:
virtual int f(void) = 0;
};
class Derived : public Base
{
public:
int f(void);
};
int Derived::f(void)
{
// do something here
}
Further, post runnable code if possible. Iow add
int main()
{
Derived d;
d.f();
}
to your code sample
Make all your functions in your two classes public. And why are you declaring int i? it's not used at all.
you need to declare
class Derived : public Base
{
protected:
virtual int f(void);
}
I suppose your pure virtual function call comes from Base class using f in another of it's methods.
I want to know the below code is correct or not
class A
{
public :
int show (int x, int y);
};
class B : public A
{
public :
float show (int a, int b); // can i overload this function ?
};
the show function is present in both base and derived class with different written types.
I know function overloading concept (can not overload with different return types).
Is this possible to do so?
The code will be compiled successfully. The method A::show will not be overloaded but hidden.
You can call this method with the scope operator.
Check this link or this link
Class A
{
Public :
virtual int show (int x, inty) = 0;
};
class B:Public A
{
Public :
float show (int x, int y);
};
When i declare base obj and point it to derived class :
A aObj;
B bObj;
aObju = &bObj;
bObj.Show(); // Which function will be called base class or derived class?
If you create a derived class object like
1)
B b;
b.show();
OR
2)
A* b = new B();
b->show();
Will always look into derived class, and call B::show().
This is for your particular example, where no virtual functions are present, if virtual functions are present in the base class, the second case can give different results in other cases, but in this particular example even base class virtual functions will make no difference.
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.