I have the following classes:
class Base{
public:
virtual int do_Something();
};
class ChildA : public Base {
public:
int do_Something(); // ChildA does something
};
class ChildB : public Base {
public:
int do_Something(); // ChildB does something
};
In my main.cpp I want to create an object ChildA() or ChildB() based on a specific configuration that the user sets.
My attempt, inside a function main() is:
...
int config = 1; // selected by the user
Base* classe;
std::cout<<typeid(classe).name() << std::endl; // check class name
if (config==0){
classe= new ChildA();
}
else if (config==1){
classe= new ChildB();
std::cout<<typeid(classe).name() << std::endl; // check class name
}
...
Problem
I expect the printed names to be different. Instead, the output is:
P4Base
P4Base
The problem here is classe (Base *) is not polymorphic. It's a simple pointer. You can see it in the output. On Linux with GCC it's: P4Base, pointer to Base
What you want is typeid(*classe).name(). The output is 6ChildB, object of type ChildB.
Polymorphism won't change the type of the pointer (neither static type nor dynamic type) but it changes the dynamic type of the object.
The comment // check class name is wrong. The line
std::cout<<typeid(classe).name() << std::endl;
doesn't check the class but the pointer.
Related
I have the problem that i need to check if a given type is the same as one specific one.
Simple example:
class Base {
public:
virtual void hi() = 0;
};
class A : public Base {
public:
void hi() { printf("Hi! I am A\n"); }
};
class B : public Base {
public:
void hi() { printf("Hi! I am B\n"); }
};
void isA(Base* something) {
// 1
if (something.is(A)) {
A* aSomething = (A*)something;
aSomething->hi();
}
// 2
something->hi();
}
Output:
Hi! I am A
Hi! I am A
The problem is that i have no RTTI enabled (and can't enable it) so i do not have dynamic_cast or typeid(...). But the program somehow still knows which type it is, as the part after // 2 still works correctly including polymorphism.
In my exact scenareo, A is a template. So i only need to check if the given pointer to the base is of type A with the same template arguments.
Let's say i'm having the following classes in c++
class Animal{}
class Dog : public Animal {
int barkingVolume;
}
However, i don't have the header file for Dog class. But i have the object of Dog of type Animal at runtime.
The question is how I can access the variable barkingVolume?
Animal animalButDogObject;//someone has set the value at runtime
I need to access barkingVolume from animalButDogObject.
Actual scenario from COM/Directshow: I'm having IBaseFilter object which is of type IVendorFilter(custom filter from 3rd party vendor which extended IBaseFilter). While debugging using Visual studio i can see the type is IVendorFilter and it has variables which i need to change. However i cannot figure out how to do it. I cannot find anything like a reflection/evalutation in CPP
I'd rather comment than post an answer, but can't due to lack of reputation, so here we go.
This is pretty bad, but if you know the exact layout of the class you must access, you could just forward declare the whole thing and reinterpret_cast the object you need.
// FooBar.cpp or something
namespace FooBar
{
class Foo {};
class Bar : public Foo
{
public:
Bar(int ival, float fval) : ival(ival), fval(fval) {}
int ival = 0;
float fval = 0.0f;
};
}
// OtherFile.cpp
class ForwardDeclaredBar
{
public:
int ival;
float fval;
};
#include <iostream>
int main()
{
FooBar::Foo* foo = new FooBar::Bar(3, 2.7f);
auto bar = reinterpret_cast<ForwardDeclaredBar*>(foo);
std::cout << "ival = " << bar->ival << ", fval = " << bar->fval << std::endl; // shows expected values
return 0;
}
Again, this is pretty bad since any changes to the "real" class will mess up your result (reinterpret_cast will just shove whatever data it finds into the format you specified).
There are probably many other reasons which I've no idea about. I'm also unsure how well (if at all) this plays with more complex objects.
declare method on Animal (base) class and overwrite it on Dog (derived) class.
// Base class
class Animal
{
public:
virtual int getBarkingVolume() = 0;
};
// Derived class
class Dog : public Animal
{
private:
int barkingVolume = 8;
public:
int getBarkingVolume()
{
return barkingVolume;
}
};
In main method has Animal (base) type and each derived class that implements the appropriate method (getBarkingVolume) will be compatible with that type.
int main()
{
Animal* animal = new Dog();
std::cout<<"barking: "<< animal->getBarkingVolume();
}
Edit :
The problem is in the GoFish.h file, in the constructor to
be specific, where it is trying to instantiate the players object.
The compiler throws the following error message : no member named 'noOfBooks' in 'Player'
GoFish() {players = new GoFishPlayer[2];} // Instantiate two players
Object Slicing seems to be one of the most ambiguous concepts in OOP for beginners. I have been working on this card game in C++, where I have a base class called, Player and a derived class called GoFishPlayer. When trying to access the methods of a GoFishPlayer object referenced back to a Player Object, the program tends to slice off the specific methods and attributes for the derived class, thus making it a clone of the base object. Is there any way to overcome this problem?
Game.h
Abstract class Game : which forms the foundation for both the games -
GoFish and CrazyEights
class Game {
protected:
Deck* deck;
Player* players;
int player_id;
public:
Game(){
deck = Deck::get_DeckInstance(); // Get Singleton instance
player_id = choosePlayer();
players = NULL;
}
....
}
GoFish.h
Derived Class GoFish - The Problem is here in the constructor when I am trying to instantiate a Player object derived from the Game Class
class GoFish : public Game{
static GoFish* goFish;
GoFish() {players = new GoFishPlayer[2];} // Instantiate two players
public:
static GoFish* get_GoFishInstance() {
if(goFish == NULL)
goFish = new GoFish();
return goFish;
}
Player.h
class Player{
protected:
std::string playerName;
Hand hand;
bool win;
public:
Player(){
playerName = "Computer"; // Sets default AI name to Computer
hand = Hand(); // Instatiate the hand object
win = false;
}
....
GoFishPlayer.h
class GoFishPlayer : public Player {
private:
std::vector <int> books;
int no_of_books;
public:
GoFishPlayer() {
no_of_books = 0;
books.resize(13);
}
int noOfBooks(){return no_of_books;}
void booksScored() {no_of_books++;}
bool checkHand() {}
....
The wording of your question seems ambiguous to me but as best as I understand you're trying to access methods of GoFishPlayer through a reference to a Player object? This isn't a problem caused by object slicing, it's just how polymorphism works.
You need to cast the reference of the Player object so that it becomes a reference to a GoFishPlayer object.
class Parent
{
public:
void foo() { std::cout << "I'm a parent" << std::endl; }
};
class Derived : public Parent
{
public:
void bar() { std::cout << "I'm a derived" << std::endl; }
};
int main()
{
Derived d;
// reference to a derived class stored as a prent reference
// you can't access derived methods through this
Parent& p_ref = d;
// this won't work
// p_ref.bar();
Derived& d_ref = static_cast<Derived&>(p_ref);
// this works
d_ref.bar();
}
This only works if you definitely know that p_ref is actually of type Derived, or that it is of a type that inherits from Derived. If you can't be sure you need to do a runtime check using dynamic_cast and then catch any std::bad_cast exceptions that are thrown.
I have an assignment that requires two classes to be derived from a base class. I am having issues getting the derived classes to call the base class constructor and successfully set the inherited variables. I recreated the issue with a dummy program for simplicity since the assignment is much longer.
#include <iostream>
class ParentClass {
public:
ParentClass(int theField1, int junk);
ParentClass() {}
virtual void printField();
virtual void setField(int nf);
protected:
int field1;
};
class ChildClass : public ParentClass {
public:
ChildClass(int theField1);
void printField();
void setField(int nf);
};
ParentClass::ParentClass(int theField1, int junk) {
field1 = theField1;
}
ChildClass::ChildClass(int theField1) {
ParentClass::ParentClass(theField1, 3);
}
void ParentClass::printField() {
std::cout << "The field = " << field1 << std::endl;
}
void ChildClass::printField() {
ParentClass::printField();
std::cout << "Some other stuff." << std::endl;
}
void ParentClass::setField(int nf) {
field1 = nf;
}
void ChildClass::setField(int nf) {
ParentClass::setField(nf);
}
int main() {
ChildClass* myChild = new ChildClass(777);
ChildClass child2(888);
myChild->printField();
child2.printField();
myChild->setField(10);
myChild->printField();
child2.setField(20);
child2.printField();
return 0;
}
Running this gives me the following output:
The field = 0
Some other stuff.
The field = 4197296
Some other stuff.
The field = 10
Some other stuff.
The field = 20
Some other stuff.
Why do the first two attempts not work? Calling the constructor should be initializing the variables to the value passed as a parameter, but they are not actually set until I specifically call a mutator function. I tried a third class which used the parent mutator function in its constructor rather than the parent constructor:
class StepChild : public ParentClass {
public:
StepChild(int nf);
};
StepChild::StepChild(int nf) {
ParentClass::setField(nf);
}
The object as defined in main:
StepChild* step = new StepChild(30);
step->printField();
The output:
The field = 30
Where am I going wrong that attempting to use the parent constructor is not properly initializing these variables?
I also tried changing the parent class to be not virtual, and it worked as well, so it doesn't appear to be an issue with the parent class.
Use initialiser lists:
ParentClass::ParentClass(int theField1, int junk)
: field1(theField1)
{ }
ChildClass::ChildClass(int theField1)
: ParentClass(theField1, 3)
{ }
The following - from your code - creates a temporary ParentClass object and throws it away - that has no affect on the ChildClass object under construction:
ParentClass::ParentClass(theField1, 3); // temporary
If you make the parameters match, you can also do it the c++11 way by putting
using ParentClass::ParentClass( int, int );
in your ChildClass class definition. It is the same as invoking the parent constructor from the ChildClass constructor initialiser list, but a little less esoteric.
Not sure but I find something wrong in the way you are calling base class constructor.
try this way to call base class constructor and see if the problem is solved.
I got an elegant answer yesterday for my question regarding polymorphic object members.
But now I am facing the problem that the variable isn't really behaving the way I expected it to. The following code is being used:
#include <iostream>
#include <math.h>
using std::cin;
using std::cout;
using std::endl;
class Com
{
public:
virtual void setReady()
{
cout << "Com" << endl;
}
};
class DerivedCom : public Com
{
public:
void setReady()
{
cout << "DCom" << endl;
}
void somethingElse()
{
cout << "else" << endl;
}
};
class BaseClass
{
public:
Com* com;
public:
BaseClass(Com* c = new Com) : com(c)
{
}
virtual void setReady()
{
com->setReady();
}
};
class DerivedClass : public BaseClass
{
// the call to somethingElse() won't compile if I leave out this declaration
protected:
DerivedCom* com;
public:
DerivedClass() : BaseClass(new DerivedCom)
{
}
void setReady()
{
// This line causes a segfault if I put in the declaration earlier
this->com->setReady();
// This line won't compile if I leave out the declaration earlier
this->com->somethingElse();
}
};
int main()
{
DerivedClass* inst = new DerivedClass();
inst->setReady();
return 0;
}
The problem is, that DerivedClass::com is in fact of type DerivedCom but I can't access any DerivedCom-specific methods as the compiler won't find them. If I put in an extra re-declaration DerivedCom* com, the compiler will find the methods but I get segmentation faults.
Remove that extra declaration.
If you are sure that a Com* is a DerivedCom* then you can static_cast it.
static_cast<DerivedCom*>(this->com)->somethingElse();
This will likely crash it you're wrong however. So if you are not sure then you can dynamic_cast it
DerivedCom* dcom = dynamic_cast<DerivedCom*>(this->com);
if (dcom)
dcom->somethingElse();
dynamic_cast will return NULL if the object isn't of the type you asked for.
The reason for the segmentation faults is that you arent declaring the variable again with a different type, you are actually defining a new pointer in the derived class, one that is never initialized. Thus this->com->... will access the derived class com and crash since it is an uninitialized pointer.
What you are trying to do though, is to change the type of the member pointer. You could do that by making the type of the member pointer as a template variable, as follows
template <class ComType>
class BaseClassTemplate
{
ComType* com;
...;
};
typedef BaseClassTemplate<Com> BaseClass;
class DerivedClass : public BaseClassTemplate<DerivedCom>
{
...;
};
However this makes the base class a template, so to get it as you want it, you need to make an instantiation of BaseClass<Com> to get your version of base class. You can either make it a derived class or just a typedef as i have shown.