Adding default arguments to virtual methods - c++

In the following code, I would like to add new default argument 'z' to 'func' method without modifying subclasses. I get error C2259: 'CTest' : cannot instantiate abstract class error.
Is there anyway to do this without modifying all subclasses?
class ITest
{
public:
virtual void func(int x, int y, char c, int z = 1) = 0;
};
class CTest : public ITest
{
public:
void func(int x, int y, char c)
{
}
};

What you want is not directly possible. The existing classes don't know of the z parameter, so can't use it. If you want to provide some new subclasses whose clients will be aware of the z and be able to use it, you can do this:
class ITest
{
public:
virtual void func(int x, int y, char c) = 0;
virtual void func(int x, int y, char c, int z)
{ func(x, y, c); }
};
This way, old classes work just as before, as will clients who call the 3-parameter version. You're also giving the option of new subclasses using z and new clients using the 4-parameter version.

You have to modify your func() method in subclass in order to make it match the one from parent class. Either way, you'll get this error: cannot instantiate abstract class error.

You could add private data and initialize it as 1
class ITest
{
public:
ITest(): z(1) {}
virtual void func(int x, int y, char c) = 0;
private:
int z;
};

Related

Multiple definition with 2 header files

I am using CodeBlocks.
In C++, I have 3 header files and 3 cpp files like below.
Base.h
class Base
{
public:
virtual int funky(int x, int y);
};
Base.cpp
int funky(int x, int y) {
return x+y;
}
FirstClass.h
class FirstClass: public Base
{
public:
virtual int funky(int x, int y);
};
FirstClass.cpp
int funky(int x, int y) {
return x+y;
}
SecondClass.h
class SecondClass: public Base
{
public:
virtual int funky(int x, int y);
};
SecondClass.cpp
int funky(int x, int y) {
return x+y;
}
In this condition I take error of "multiple definition." But, I have to use these functions with the same names.
I tried
int funky (int x, int y) override;
but it did not work.
I need all three function, because when I want to call them like below and if they are defined like above, I cannot reach them.
vector<Base> BASE = {FirstClass(), SecondClass()};
BASE[1]->funky(1,2)
Do you have any suggestion? I am open to another approach to this problem.
Thank you.
In the above code sample, you defining funky in two different cpp files but have declared in your class. So following should be the correct format:
FirstClass.cpp
int FirstClass::funky(int x, int y) {
return x+y;
}
SecondClass.cpp
int SecondClass::funky(int x, int y) {
return x+y;
}
main.cpp
FirstClass a;
SecondClass b;
cout<<a.funky(1,2)<<" "<<b.funky(3,4)<<endl;
int funky(int x, int y) in both your .cpp files are defined as free functions that has nothing to do with the classes you've defined. They have the same signature and you therefore get a linking problem with multiple definitions.
I suggest you make the destructor in the base class virtual, just in case you want to destroy objects through a base class pointer.
Inheriting, overriding and defining the member functions could look like this:
class Base {
public:
virtual ~Base() = default; // virtual destructor
virtual int funky(int x, int y) = 0; // = 0 added to make it pure virtual
};
class FirstClass : public Base { // inherit
public:
int funky(int x, int y) override; // now you can override
};
int FirstClass::funky(int x, int y) { // class member function definition
return x+y;
}
And you need to do the same for SecondClass.
You should not use vector<Base> though. You will not store Base objects but most probably pointers to objects of types derived from Base, like FirstClass and SecondClass. I suggest using the smart pointer std::unique_ptr for this:
#include <memory>
int main() {
std::vector<std::unique_ptr<Base>> BASE;
BASE.emplace_back(std::make_unique<FirstClass>());
BASE.emplace_back(std::make_unique<SecondClass>());
std::cout << BASE[0]->funky(2,3) << '\n';
std::cout << BASE[1]->funky(2,3) << '\n';
}
Demo

I can't use subclass specific funcitons when I add them to a vector using parent class pointers

I am trying to create an "alien invaders" game by myself. In order to create enemies and player, I created a class called "entity" and made subclasses of it. Like Player, shootingEnemy, IdleEnemy. When coding I realised gathering them in a vector<Entity> would make my collision detection function much easier.
After searching on the internet I learned this is called "object slicing" and makes copies of of ony le base part of objects.
So the final version became this.
int main()
{
int BoardWidth = 50;
int BoardLength = 30;
vector<Bullet> bullets;
vector<Entity*> SpaceShips;
setup(SpaceShips, BoardWidth, BoardLength);
double ElapsedTime = 0;
int PreviousRoundSec = 0;
int PreviousRoundQSec = 0;
DrawGame(BoardWidth, BoardLength, SpaceShips, bullets);
int IsGameOver = 0;
auto start = chrono::steady_clock::now();
while(!IsGameOver)
{
// Updates EverySecond
if ((int)(ElapsedTime / 1000) > PreviousRoundSec)
{
PreviousRoundSec = (int)(ElapsedTime / 1000);
}
// Updates every quarter of a second
if ((int)(ElapsedTime / 250) > PreviousRoundQSec)
{
PreviousRoundQSec = (int)(ElapsedTime / 250);
}
// To keep time
auto end = chrono::steady_clock::now();
ElapsedTime = chrono::duration_cast<chrono::milliseconds>(end - start).count();
}
if (IsGameOver == 1)
{
// conjualations
}
else if (IsGameOver == 2)
{
// GameOver
}
return 0;
}
But when I try use some subclass specific functions I get an compiler error saying 'CLASS "Entity" does not have any member called "shoot"'.
I am trying to practice classes and polymorphism so I do not even know this has a solution because compiler doesn't have any way of knowing which element of this vector belongs to which subclass.
Also this is my classes header page in case needed.
class Entity
{
public:
int x;
int y;
int width;
int length;
int hp;
bool shooting;
public:
Entity(int x, int y, int width, int length, int hp, bool shooting): x(x), y(y), width(width), length(length), hp(hp), shooting(shooting) {}
};
class Bullet : public Entity
{
private:
char dir;
int ID;
public:
Bullet(int x, int y, char GivenDir, int GivenID) : Entity(x, y, 1, 1, 1, false) { dir = GivenDir; ID = GivenID; }
void Move();
void IfHit(vector<Entity>& SpaceShips);
void IfOut();
};
class Player : public Entity
{
private:
char action = 'a';
public:
Player(int x, int y, int hp) : Entity(x, y, 3, 2, hp, true) {}
void GetAction();
void Move();
void Shoot(vector<Bullet>& bullets);
bool IfHit(vector<Entity>& SpaceShips, vector<Bullet>& bullets);
};
class IdleEnemy : public Entity
{
public:
IdleEnemy(int x, int y, int hp) : Entity(x, y, 3, 2, hp, false){}
bool IfHit(Player* player, vector<Bullet> &bullets);
void Move(char HordDir);
};
class ShootingEnemy : public Entity
{
public:
ShootingEnemy(int x, int y, int hp) : Entity(x, y, 3, 2, hp, true) {}
void Shoot(vector<Bullet> &bullets);
bool IfHit(Player* player, vector<Bullet> &bullets);
void Move(char HordDir);
};
You need to check runtime polymorphism in C++. Let's check it out how can you do that. First of all, you need to change your Entity class interface. You need to add virtual or pure virtual functions. I have added pure virtual function;
class Entity
{
public:
int x;
int y;
int width;
int length;
int hp;
bool shooting;
public:
Entity(int x, int y, int width, int length, int hp, bool shooting) : x(x), y(y), width(width), length(length), hp(hp), shooting(shooting) {}
void virtual Move() = 0; // pure virtual function
void virtual IfHit() = 0; // pure virtual function
};
Virtual functions are overridable functions. Also, they have implementations but when we are talking about pure virtual functions they only provide an interface for the class. You need to override that function in your derived class. When you are implementing your derived class you need to do like this,
class Bullet : public Entity
{
private:
char dir;
int ID;
public:
Bullet(int x, int y, char GivenDir, int GivenID) : Entity(x, y, 1, 1, 1, false) { dir = GivenDir; ID = GivenID; }
void Move()override;
void IfHit();
void IfOut();
};
class Player : public Entity
{
private:
char action = 'a';
public:
Player(int x, int y, int hp) : Entity(x, y, 3, 2, hp, true) {}
void GetAction();
void Move();
void Shoot(vector<Bullet>& bullets);
void IfHit()override {//code};
};
class IdleEnemy : public Entity
{
public:
IdleEnemy(int x, int y, int hp) : Entity(x, y, 3, 2, hp, false) {}
void IfHit()override;
void Move()override;
};
class ShootingEnemy : public Entity
{
public:
ShootingEnemy(int x, int y, int hp) : Entity(x, y, 3, 2, hp, true) {}
void Shoot(vector<Bullet>& bullets);
void IfHit()override;
void Move()override;
};
These functions can be implemented either inline or in a source file. Also, there is an important point of these functions is the return value, function signature, and names' must be identical unless you do not use covariant return type.
As seen in the derived classes some of the functions are not common. I know your question how can I use that :) As mentioned ttemple in the comments you need to use dynamic_cast operator.
int main()
{
Entity* ptr = new ShootingEnemy{ 1,2,4 };
ptr->Move();
ptr->IfHit();
if (auto SE = dynamic_cast<ShootingEnemy*>(ptr))
SE->Shoot(...);
}
dynamic_cast operator is a runtime conversion operator. It converts the type of base class pointer to the derived class. It is called downcasting. Also, it checks that base class pointer points to the target derived class. If the dynamic_cast operation is completed with fail then it returns null and if statement becomes fail. Via that way, you can use runtime polymorphism and class member functions.
By the way, avoid object slicing as possible. You are losing derived class properties.
To better understanding please refer classes dynamic_cast
The compiler tells you the truth. You have a pointer to an Entity, which obviously does not have Shoot method in its interface, so how could you possibly call it without any cast?
The idea behind dynamic polymorphism which you are trying to implement here is about having a common interface (your base class, Entity), with specific implementation in each sub-class. So, publicly available methods signatures are going to be common for all subclasses, but not the implementations.
From the design perspective, cleanest approach would be to rename Entity to ShootableEntity and declare a pure virtual Shoot method in there. Then all sub-classes shall provide some implementation.
If not all of them implement Shoot, yet you are trying to use them generically in such manner, maybe you should reconsider the approach, eg. create two containers - for shootable entities and for non-shootable entities. Then, when iterating over shootable-entities (instances of classes which actually subclass ShootableEntity, which contain Shoot declaration), you could call Shoot on base class' pointer without any problems.
Your Entity does not represent any common interface, however. So, if you are trying to make use of polymorphism (so, you have a pointer to the base class, yet behind that pointer there's some concrete instance), such class won't do you any good.
In fact, the doc itself has a great explanation: http://www.cplusplus.com/doc/tutorial/polymorphism/

Bad practice to call base methods in derived constructors?

I was just wondering on the most efficient way of setting inherited members was and if the following code is alright to use:
This is the declaration of the base class:
class cEntity{
private:
int X, Y;
int Height, Width;
public:
cEntity();
cEntity(int x,int y,int h,int w);
~cEntity();
void setX(int x){X=x;};
void setY(int y){Y=y;};
void setCoords(int x, int y){X=x;Y=y;};
void setHeight(int h){Height = h;};
void setWidth(int w){Width = w;};
void setArea(int h, int w){Height=h;Width=w;};
int getX(){return X;};
int getY(){return Y;};
//void getXY(int,int);
int getHeight(){return Height;};
int getWidth(){return Width;};
//void getArea(int,int);
};
and here is the constructor of the derived class:
cOrganism::cOrganism () {
setCoords(0,0);
setArea(0,0);
Name = "UNKNOWN";
Health = 100;
MaxHealth = 100;
HealthHiRange =100;
HealthLoRange = 100;
};
So. Is is alright to call the setCoords() and setArea() in the derived class' constructor?
It's alright, but you can do much better by calling the base constructor:
cOrganism::cOrganism() : cEntity(0, 0, 0, 0) {
// other stuff
}
In fact, you should initialize your new, derived members the same way:
cOrganism::cOrganism()
: cEntity(0, 0, 0, 0),
Name("UNKNOWN"),
Health(100),
...
{
}
(You might also want to read up a bit on general C++ class design: If you expose getters and setters to all your private variables, something isn't quite right. A class is supposed to encapsulate a model, while you're doing essentially the opposite. But that's not a technical error.)
Much better to call it like this:
cOrganism::cOrganism () : cEntity(0,0,0,0) {
Name = "UNKNOWN";
Health = 100;
MaxHealth = 100;
HealthHiRange =100;
HealthLoRange = 100;
}
Or even better:
cOrganism::cOrganism ()
: cEntity(0,0,0,0), Name("UNKNOWN"), Health(100),
MaxHealth(100), HealthHiRange(100), HealthLoRange(100)
{}
That way the base class members are set as the base class implementation is constructed.
If the default constructor of the base class already intializes it to good values you don't have to do it all.
Otherwise the good solution is something like below.
class A
{
int x;
public:
A( int xin) :x(xin) {}
};
class B : public A
{
int y;
public:
B( int xin , int yin ) :A(xin) , y(yin) {}
};
Notice A(xin) in B constructor. This will called pass xin to the A constructor.
If you have something like integers it doesn't really matter what you do. But if A::X was actually a heavy weight object. With your approach A::x will be constructed once with default constructor and then assigned again when setCoords() is called from derived class constructor. My solution will ensure A::x* is only constructed once and that too with all the right value of its parameters.
More details here

Class member function pointers in C++

I want to call a member function of another class on an object, but I cant seem to figure out how this works. As example code on how it should work:
Class A {
void somefunction(int x);
}
Class B : A {
void someotherfunction(int x);
}
Class C {
void x() {
callY(&ofthefunction);
} //here you call the function, you dont have an object yet, and you don't know the argument yet, this will be found in function callY
void Y(*thefunction) {
find int x;
if(something)
A a = find a;
a->thefunction(x);
else
B b = find b;
b->thefunction(x);
}
}
I hope this makes sence, It is also possible to split this in 2 methods, Y1 and Y2, but seeing as 90% of the code is the same (finding things in a XML file), only the object and argument where to save it is different, i'd like to do this
You can use something known as a virtual function. By the way, your syntax is hideous, it's class not Class, you need braces for your conditionals, and a judicious application of public, some extra semicolons, etc. It would be appreciated if you would go near a compiler before coming here, y'know.
class A {
public:
virtual void somefunction(int x);
};
class B : public A {
public:
virtual void somefunction(int x);
};
void func(A& a) {
int x = 0;
// Do something to find x
a.somefunction(x);
// calls A::somefunction if this refers to an A
// or B::somefunction if it's a B
}
int main() {
A a;
func(a); // calls A::somefunction
B b;
func(b); // calls B::somefunction
}
What you want to do can be done, although I woudn't solve it this way:
class A {
public:
virtual int doit(int x) { return x+1; }
};
class B : public A {
public:
int doit2(int x) { return x*3; }
int doit(int x) { return x*2; }
};
int foo(int (A::*func)(int), int x, bool usea) {
if (usea) {
A a;
return (a.*func)(x);
} else {
B b;
return (b.*func)(x);
}
}
int main() {
int (A::*bla)(int) = &A::doit;
foo(bla, 3, true);
foo(bla, 3, false);
}
However, for this to work, the following has to be satisfied:
You must use function pointers of the base class (e.g. int (A::*bla)(int)), otherwise you won't be able to call it on that base class (e.g. int (B::*bla)(int) can only be used on B instances, not on A instances, even if the method is already defined in A).
The methods must have the same names as in the base class
To use overriding (e.g. different impl in derived class), you have to use virtual functions.
But I would rather rethink your design...
No, that won't work at all. A pointer to a member of A will always point to that function, even when it's called on B because B inherits from A.
You need to use virtual functions. I see DeadMG has beaten me to it.

Override number of parameters of pure virtual functions

I have implemented the following interface:
template <typename T>
class Variable
{
public:
Variable (T v) : m_value (v) {}
virtual void Callback () = 0;
private:
T m_value;
};
A proper derived class would be defined like this:
class Derived : public Variable<int>
{
public:
Derived (int v) : Variable<int> (v) {}
void Callback () {}
};
However, I would like to derive classes where Callback accepts different parameters (eg: void Callback (int a, int b)).
Is there a way to do it?
This is a problem I ran in a number of times.
This is impossible, and for good reasons, but there are ways to achieve essentially the same thing. Personally, I now use:
struct Base
{
virtual void execute() = 0;
virtual ~Base {}
};
class Derived: public Base
{
public:
Derived(int a, int b): mA(a), mB(b), mR(0) {}
int getResult() const { return mR; }
virtual void execute() { mR = mA + mB; }
private:
int mA, mB, mR;
};
In action:
int main(int argc, char* argv[])
{
std::unique_ptr<Base> derived(new Derived(1,2));
derived->execute();
return 0;
} // main
Even if such a thing were possible, it no longer makes much sense to have it as a virtual function, as the derived instantiations couldn't be called polymorphically via a pointer to the base class.
don't think this will be possible, because you can never interface it back to Variable.
This is what i mean
int a=0; int b = 0;
Variable<int>* derived = new Derived();
derived->Callback(a, b); //this won't compile because Variable<int> does not have Callback with 2 vars.
I know this there is an accepted answer, but there is one (ugly) way to achieve what you want, although I would not recommend it:
template <typename T>
class Variable
{
public:
Variable (T v) : m_value (v) {}
virtual void Callback (const char *values, ...) = 0;
private:
T m_value;
};
class Derived : public Variable<int>
{
public:
Derived (int v) : Variable<int> (v) {}
virtual void Callback (const char *values, ...) {
}
};
Now, you can use:
int a=0;
double b = 0;
Variable<int>* derived = new Derived(3);
derived->Callback("");
derived->Callback("df", a, b);
You need the values argument in order to obtain the remaining arguments inside the method. You also need to know the argument types, and pass them like printf does.
This method is error prone, as you must match the argument types on values with the real argument types.
You will have to add an overload of Callback in the base class that accepts these parameters. It would also be possible to do bad things, like accept a void*, or pass in a raw pointer-to-bytes.
The only scenario in which it is valid to alter virtual function signature is when you override the return value to something polymorphic to the original return value, e.g. *this.