I have an abstract class Player and its children AI and Human. In my main, when I create two objects Human and AI it works fine. But once I use them as parameters in a function that is waiting for Player pointer type, then their type is no longer AI and Human but both are Player objects.
Game.hpp :
#include "Player.hpp"
#include "Human.hpp"
class Game {
private:
Player *j1, *j2;
public:
Game();
Game(Player*, Player*);
void setP1(Player*);
void setP2(Player*);
Player* getP1();
Player* getP2();
};
Game.cpp :
#include "Game.hpp"
Game::Game(){
}
Game::Game(Player *pp1, Player *pp2){
p1 = pp1;
p2 = pp2;
}
void Game::setP1(Player *pp1){
p1 = pp1;
}
void Game::setP2(Player *pp2){
p2 = pp2;
}
Player* Game::getP1(){
return p1;
}
Player* Game::getP2(){
return p2;
}
Player.hpp :
#ifndef PLAYER_H
#define PLAYER_H
#include <string>
using std::string;
class Player {
protected:
string nom;
int age;
public:
Player();
Player(string, int);
void setNom(string);
void setAge(int);
string getNom();
int getAge();
virtual void upAge() = 0;
};
#endif
Here is the main.cpp :
#include "Player.hpp"
#include "Human.hpp"
#include "Game.hpp"
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
int main(){
Player *j;
Human h;
Game Game;
cout << typeid(h).name() << endl;
Game.setJ1(&h);
cout << typeid(Game.getJ1()).name() << endl;
return 0;
}
I would like the two cout to display the same result. But the first displays Human, and the second displays Player. How can I handle this ?
EDIT 1 : added Player.hpp file.
Base class Player must contain a virtual function to get the type name as derived class.
check typeid below example from cpp reference.
#include <iostream>
#include <string>
#include <typeinfo>
struct Base {}; // non-polymorphic
struct Derived : Base {};
struct Base2 { virtual void foo() {} }; // polymorphic
struct Derived2 : Base2 {};
int main() {
// Non-polymorphic lvalue is a static type
Derived d1;
Base& b1 = d1;
std::cout << "reference to non-polymorphic base: " << typeid(b1).name() << '\n';
Derived2 d2;
Base2& b2 = d2;
std::cout << "reference to polymorphic base: " << typeid(b2).name() << '\n';
}
Possible output:
reference to non-polymorphic base: 4Base
reference to polymorphic base: 8Derived2
Related
When I create a class A object with a reference to class C, class B gives the error of:
Error C2512 'A': no appropriate default constructor available
Class A
class A
{
public:
C* cPointer;
A(C* arg)
{
cPointer = arg;
}
};
Class B
class B:
public A
{
public:
B()
{
}
};
If I add an empty constructor to class A it doesn't give errors but when I try to access cPointer it returns an empty address of 0000000000;
A()
{
}
How can I solve this problem?
Edit: example
int main()
{
C cObject;
A a(&cObject);
return 0;
}
Result: Severity Code Description Project File Line Suppression State
Error C2512 'A': no appropriate default constructor available
As I mentioned before if I put empty constructor to A it works but i cant use cPointer because it set to 0.
in class B:
cout << "Poniter: " << cPointer << endl;
result:
Pointer: 0000000000000000
Okay here is the actual code:
Skill.h (class C in example)
#pragma once
#include <iostream>
#include <vector>
#include "Unit.h"
using namespace std;
class Skill
{
public:
Unit* unitPtr;
Skill()
{
}
Skill(Unit* unit)
{
unitPtr = unit;
}
void SetUnit(Unit* unit)
{
unitPtr = unit;
}
vector <Skill *> attacks;
vector <Skill *> utilities;
vector <Skill *> movement;
};
Unit.h (class A in example)
#pragma once
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Skill;
class Unit
{
public:
Skill* skillPtr;
Unit(Skill* skill)
{
skillPtr = skill;
}
void Setup();
string name;
vector <Unit* > heroes;
vector <Unit* > monsters;
};
Hero.h (class B in example)
#pragma once
#include "Unit.h"
class Hero :
public Unit
{
public:
Hero() : Unit(skillPtr)
{
cout << "Pointer: " << skillPtr << endl;
}
};
Main
int main()
{
Skill skill;
Unit unit(&skill);
skill.SetUnit(&unit);
unit.Setup();
return 0;
}
class B: public A {
B() { }
}
When a child class's constructor is called, it first initializes its parent portion by calling a parent constructor. Since you didn't specify one here, the B constructor is trying to call the default A constructor, but one doesn't exist!
To call the constructor you made explicitly, you can do:
class B: public A {
B(): A(Some_C_Pointer) { }
}
I am unable to call private methods of derived class using pointer to base class returned by Factory method.
I would like to return a unique_ptr to Cat when user is running on WIN and unique_ptr to Dog when user is running on Linux.
Base.h pure virtual class
#include <iostream>
#include <memory>
class Base
{
public:
virtual void echo() = 0;
};
Cat.h - derived class of Base
#include "Base.h"
class Cat : public Base
{
public:
void echo();
void CatPrivateFunction();
};
Cat.cpp
#include "Cat.h"
void Cat::echo()
{
std::cout << "In echo()" << std::endl;
}
void Cat::CatPrivateFunction()
{
std::cout << "In CatPrivateFunction()" << std::endl;
}
Dog.h - derived class of Base
#include "Base.h"
class Dog
{
void echo();
void DogPrivateFunction();
};
Dog.cpp
#include "Dog.h"
void Dog::echo()
{
std::cout << "In echo()" << std::endl;
}
void Dog::DogPrivateFunction()
{
std::cout << "In DogPrivateFunction()" << std::endl;
}
BaseFactory.h
#ifdef _WIN32
#include "Cat.h"
#elif __linux__
#include "Dog.h"
#endif
#include <memory>
class BaseFactory
{
public:
static std::unique_ptr<Base> createBase();
};
BaseFactory.cpp
#include "BaseFactory.h"
std::unique_ptr<Base> BaseFactory::createBase()
{
#ifdef __linux__
return std::unique_ptr<Base>(new Dog{});
#elif _WIN32
return std::unique_ptr<Base>(new Cat{});;
#endif
}
In the following script
#include "BaseFactory.h"
int main()
{
std::unique_ptr<Base> p = BaseFactory::createBase();
p->echo();
p->CatPrivateFunction();
return 0;
}
I'd expect the following output
In echo()
In CatPrivateFunction()
But p->CatPrivateFunction() is failing as Base.h doesn't have CatPrivateFunction() member function.
How can this be done?
Please read about upcasting and downcasting.
What you need here is to downcast the "pointer to Base" to a "pointer to Cat".
Considering that you don't know the exact type that the pointer is pointing to, you need to use dynamic_cast and check that the result is not a null pointer:
if (auto cat = dynamic_cast<Cat*>(p.get()))
cat->CatPrivateFunction();
You can't call CatPrivateFunction() without a valid pointer/reference to a Cat object. Since you only have a pointer to a Base, you would have to use dynamic_cast to test if that Base pointer is pointing at a Cat or not, and if so then you can call CatPrivateFunction() on it, eg:
#include "BaseFactory.h"
#include "Cat.h"
int main()
{
std::unique_ptr<Base> p = BaseFactory::createBase();
p->echo();
Cat *c = dynamic_cast<Cat*>(p.get());
if (c)
c->CatPrivateFunction();
return 0;
}
#include<iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
class base
{
public:
virtual void fun_1() { cout << "base-1\n"; }
virtual void fun_2() { cout << "base-2\n"; }
};
class derived : public base
{
public:
void fun_1() { cout << "derived-1\n"; }
void fun_2() { cout << "derived-2\n";
}
};
class caller
{
private:
base *p;
derived obj1;
p = &obj1;
public:
void me()
{
std::thread t(std::bind(&base::fun_2, p), this);
t.join();
}
};
int main()
{
caller c;
c.me();
return 0;
}
I have a written a very simple threading and polymorphism example. All I wanted to do is to call a derived function from a different class which is containing that another class object. The program fails to compile with the message p does not name a type which I could not understand why.
Your error is in line:
p = &obj1;
It is better to write like this, it should help:
class caller
{
private:
derived obj1;
base *p = &obj1;
......
};
or initialize pointer in costructor:
class caller
{
private:
derived obj1;
base *p = nullptr;
caller() : p(&obj1) {}
......
};
I'm new to object programming and to c++.
I'm applying what is taught in SoloLearn c++ course about class inheritance.
Class enemy: enemy.h
class enemy
{
public:
enemy();
~enemy();
void setAttackPower();
protected:
int aP;
};
enemy.cpp:
#include "enemy.h"
#include <iostream>
using namespace std;
enemy::enemy()
{
cout << "constructor" << endl;
}
enemy::~enemy()
{
cout << "destructor" << endl;
}
int aP=0;
void setAttackPower(int a) {
aP = a;
}
class ninja, that inherits from enemy:
ninja.h:
#include "enemy.h"
class ninja: public enemy
{
public:
ninja();
~ninja();
void attack();
};
ninja.cpp:
#include "ninja.h"
#include <iostream>
using namespace std;
ninja::ninja()
{
}
ninja::~ninja()
{
}
void attack() {
cout << "Ninja attack " << aP << endl;
}
and the error is:
identifier "aP" is undefined. I can't see the problem. Can anyone help me?
enemy.cpp
int aP=0;
You created 2 values with same name: 1st belongs to class and the 2nd is a global value. The compiler cannot deside which one you are trying to use.
I have a little problem with polymorphism. My simple code:
Animal.h
class Animal {
public:
Animal();
Animal(const Animal& orig);
virtual ~Animal();
virtual void get();
};
Animal.cpp
#include "Animal.h"
#include <iostream>
using namespace std;
Animal::Animal() {
cout << "Animal is born" << endl;
}
void Animal::get() {
cout << "get() from an Animal!" << endl;
}
Bird.h
class Bird : public Animal {
public:
Bird();
Bird(const Bird& orig);
virtual ~Bird();
void get();
};
Bird.cpp
#include "Bird.h"
#include <iostream>
using namespace std;
Bird::Bird() {
cout << "Bird is born" << endl;
}
void Bird::get() {
cout << "get() from a Bird!" << endl;
}
Chicken.h
#include "Bird.h"
class Chicken : public Bird {
public:
Chicken();
Chicken(const Chicken& orig);
virtual ~Chicken();
void get();
};
Chicken.cpp
#include "Chicken.h"
#include <iostream>
using namespace std;
Chicken::Chicken() {
cout << "Chicken is born" << endl;
}
void Chicken::get() {
cout << "get() from a Chicken!" << endl;
}
There is also a factory method returning an Animal* pointer to the concrete implementation based on input:
Factory.h
#include "Animal.h"
#include "Bird.h"
class Factory {
public:
Factory();
Factory(const Factory& orig);
virtual ~Factory();
Animal* generateAnimal();
Bird* generateBird();
};
Factory.cpp
#include "Factory.h"
#include "Animal.h"
#include "Bird.h"
#include "Chicken.h"
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
Animal* Factory::generateAnimal() {
string choice;
cout << "What do you want? 1-Animal, 2-Bird, 3-Chicken" << endl;
cin >> choice;
Animal* animal;
if (choice.at(0) == '1') {
cout << "You chose Animal" << endl;
animal = new Animal();
return animal;
} else if (choice.at(0) == '2') {
cout << "You chose Bird" << endl;
animal = new Bird();
return animal;
} else if (choice.at(0) == '3') {
cout << "You chose Chicken" << endl;
animal = new Chicken();
return animal;
} else {
cout << "Wrong input" << endl;
exit(1);
}
}
Bird* Factory::generateBird() {
string choice;
cout << "What do you want? 1-Animal, 2-Bird, 3-Chicken" << endl;
cin >> choice;
Bird* bird;
if (choice.at(0) == '2') {
cout << "You chose Bird" << endl;
bird = new Bird();
return bird;
} else if (choice.at(0) == '3') {
cout << "You chose Chicken" << endl;
bird = new Chicken();
return bird;
} else {
cout << "Wrong input" << endl;
exit(1);
}
}
I omitted ctors & dtors.
main.cpp
#include <cstdlib>
#include <iostream>
#include "Factory.h"
#include "Animal.h"
#include "Bird.h"
#include "Chicken.h"
using namespace std;
int main(int argc, char** argv) {
Factory factory;
Animal* animal = factory.generateAnimal();
animal->get();
return 0;
}
The concrete implementation of an Animal class is resolved during runtime.
It's obvious, that removing the virtual keyword from Animal class results in calling Animal implementation of get() method, whether animal* points to Bird or Chicken.
What do you want? 1-Animal, 2-Bird, 3-Chicken
3
You chose Chicken
Animal is born
Bird is born
Chicken is born
get() from an Animal!
It's also obvious, that calling the virtual get() method results in polymorphic call to the concrete subclass.
What concerns me is this situation:
Instead of
Animal* animal = factory.generateAnimal();
animal->get();
we have
Bird* bird = factory.generateBird();
bird->get();
We have a pointer to Bird class, in which the get() method is NOT declared virtual. The output is:
What do you want? 1-Animal, 2-Bird, 3-Chicken
3
You chose Chicken
Animal is born
Bird is born
Chicken is born
get() from a Chicken!
How does it happen, that call to non-virtual function results in virtual call to the subclass?
Is "virtualism" inherited? If it is, is it somehow possible to perform a non-virtual call to the pointer class, instead of implementation class?
A virtual method remains virtual in inherited classes even if you don't specify the virtual keyword. Actually in C++11 you have a way to specify that method is overridden:
class Bird {
void get() override;
}
You can even specify the virtual keyword on overridden methods just to remember it yourself but you can't "remove" the dynamic dispatch of the method.
The only thing you are allowed to do is to choose the implementation by specifying it:
Bird *bird = new Bird();
bird->Animal::get();
We have a pointer to Bird class, in which the get() method is NOT virtual.
That's wrong. It is virtual. Virtual functions cannot be made non-virtual by derived classes. The virtual keyword is just optional there, but it has no effect.
In short, yes, virtual is "inherited". In other words, you can't "change it back" from virtual to non-virtual when you inherit from a base-class. That would make the system very fragile to typos (forget virtual, and all of a sudden you call a different member depending on which route you came to the object).
Say you have a class hierarchy
class A{
void f();
};
class B : public A{
void f();
};
class C : public B{
void f();
};
\\...
class O : public N{
void f();
};
class P : public O{
virtual void f();
};
class Q : public P{
virtual void f();
};
class R : public Q{
void f();
};
\\...
class Z : public Y{
void f();
};
As soon as, traversing the hierarchy, a member is declared to be virtual, it will be so for further derived classes too. In case you are wondering, there is no way for making Z::f() non-virtual if Q::f() is virtual.
What this mean is explained in this code:
Z z;
A& a = z;
O& o = z;
P& p = z;
Q& q = z;
Z& z = z;
a.f(); //calls A::f()
o.f(); //calls O::f()
p.f(); //calls Z::f()
q.f(); //calls Z::f()
z.f(); //calls Z::f()
z.A::f(); //calls A::f()
z.R::f(); //calls R::f()
of course this assumes that O::f() is overridden.
See also my answer to a related question.