I have a very simple base class/ derived class scenario:
#include <tchar.h>
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
class BaseChannel{
private:
public:
virtual ~BaseChannel(){};
virtual void SayBoo( bool SelectAll)=0;
};
class gdbChannel: BaseChannel{
public:
void SayBoo(bool SelectAll) {if (SelectAll) cout<<"boo";}
};
class UsesChannel{
public:
BaseChannel * c;
};
int _tmain(int argc, _TCHAR* argv[])
{
gdbChannel gc;
UsesChannel uc;
// uc.c = &gc; //cannot convert gdbChannel* to BaseChannel*
uc.c = (BaseChannel*)&gc; // works
uc.c->SayBoo(true);
getch();
return 0;
}
My initial implementation, commented out above, will not compile. Can anyone explain why? I feel that since gdbChannel is explicitly an instance of BaseChannel the cast shouldn't be necessary.
That is because gdbChannel does not use public inheritance to derive from BaseChannel (the default for class types is private).
If public inheritance is what you wanted to express, just write:
class gdbChannel : public BaseChannel{
// ^^^^^^
public:
void SayBoo(bool SelectAll) {if (SelectAll) cout<<"boo";}
};
Related
I have following C++ code
Configuration.h
#include <cstdint>
typedef struct
{
uint8_t id;
uint32_t data;
} Config;
Handler.h
class HandlerBase
{
public:
typedef void (*func_ptr)(void *data);
HandlerBase(func_ptr function) : function(function) {}
private:
func_ptr function;
};
template<class T>
class Handler : public HandlerBase
{
public:
Handler() : HandlerBase(&fun_01) {}
private:
static void fun_01(void *data) {}
};
AbstractBase.h
class AbstractBase
{
public:
virtual void method_01() = 0;
virtual void method_02() = 0;
};
A.h
#include "AbstractBase.h"
#include "Handler.h"
#include "Configuration.h"
class A : public Handler<A>, public AbstractBase
{
public:
A();
void method_01();
void method_02();
private:
Config cfg;
};
A.cpp
#include "A.h"
A::A() {}
void A::method_01() {}
void A::method_02() {}
main.cpp
int main(int argc, char** argv) {
A a;
return 0;
}
In case I have steped through the code in the debugger I have noticed that whenever I create the a instance of the A class in the main the a instance contains two instances of the cfg struct. Here is the output of my debugger (I have been using the GDB along with the g++ compiler (v 4.6.3) under Netbeans IDE v8.2. under Windows 10 Pro)
EDIT_01:
I have found that I can store values only into one of the cfg instances. After assignment into the struct items
cfg.id = 0x55;
cfg.data = 0xAAAAAAAA;
I can see follwing content of the cfg structs
In case I observe the content of the memory at address 0xffffcbd0 (content of the this pointer) I see following (one byte of id item with three padding bytes followed by four bytes of the data item)
EDIT_02:
I have added below given method into the A class
void A::init()
{
cfg.id = 0x55;
cfg.data = 0xAAAAAAAA;
}
and modified the method_01 in following manner
void A::method_01()
{
if ((cfg.data == 0xAAAAAAAA) && (cfg.id == 0x55)) {
std::cout << "Config ok!" << std::endl;
}
}
The main.cpp
int main(int argc, char** argv) {
A a;
a.init();
a.method_01();
return 0;
}
prints the Config ok! message.
At the same time only one instance of cfg struct is created in case the A class inherits only from the Handler. Please can anybody tell me what is the reason for this behavior? Is there any way how to avoid this duplication of the class member? Thanks in advance.
I have following C++ code
AbstractClass_01.h
class AbstractClass_01 {
public:
virtual void method_01() = 0;
};
AbstractClass_02.h
class AbstractClass_02 {
public:
virtual void method_02() = 0;
};
ClassA.h
#include "AbstractClass_02.h"
class ClassA : public AbstractClass_02{
public:
void method_02();
void method_03();
};
ClassA.cpp
#include "ClassA.h"
void ClassA::method_02() {}
void ClassA::method_03() {}
ClassB.h
#include "AbstractClass_01.h"
#include "AbstractClass_02.h"
class ClassB : public AbstractClass_01 {
public:
ClassB(AbstractClass_02& _obj);
void method_01();
private:
AbstractClass_02 &obj;
};
ClassB.cpp
#include "ClassB.h"
#include "ClassA.h"
ClassB::ClassB(AbstractClass_02& _obj) : obj(_obj) {}
void ClassB::method_01() {
static_cast<ClassA&>(obj).method_03();
}
main.cpp
#include "ClassA.h"
#include "ClassB.h"
int main(int argc, char** argv) {
ClassA a;
ClassB b(a);
b.method_01();
return 0;
}
My question is whether the casting which I have done in the ClassB::method_01 is common C++ construct whether it is a sign of wrong design?
EDIT:
The reason why the ClassB constructor accepts references to the AbstractClass_02 instead of the ClassA is that I need to pass references to various objects which all have common interface AbstractClass_02. The problem is that this interface doesn't contain the method_03. One possible solution could be to append that method into the interface AbstractClass_02 but that method isn't cohesive with the method_02.
This is known as downcasting and is typically a sign of bad design. Based on the limited knowledge we have, it seems obvious that you should take ClassA in constructor instead of AbstractClass_01
#include "AbstractClass_01.h"
#include "ClassA.h"
class ClassB : public AbstractClass_01 {
public:
ClassB(ClassA & _obj);
void method_01();
private:
ClassA &obj;
};
But we don't know your real problem and why did you decide to go with casting or accepting interface in the first place.
I've tried to create std::map with the following way :
std::map<QString, std::shared_ptr<A> > stringToA { {QString("B"), std::shared_ptr<A>(new B())}, {QString("C"), std::shared_ptr<A>(new C())} };
Where C & B inherited from A, I've same result with std::make_shared<A>.
My question is the following : how can I initialize std::map to shared_ptr, and why the code doesn't work properly?
#include <map>
#include <memory>
#include <QString>
#include <QDebug>
class A{
public:
A(){qDebug()<<"ctorA";}
~A(){qDebug()<<"dtorA";}
};
class B : public A {
public:
B(){qDebug()<<"ctorB";}
~B(){qDebug()<<"dtorB";}
};
class C : public A {
public:
C(){qDebug()<<"ctorC";}
~C(){qDebug()<<"dtorC";}
};
std::map<QString, std::shared_ptr<A> > stringToA { {QString("B"), std::shared_ptr<A>(new B())}, {QString("C"), std::shared_ptr<A>(new C())} };
int main(int argc, char *argv[])
{
qDebug()<<"start of programm";
return 0;
}
Output is the following:
ctorA
ctorB
ctorA
ctorC
dtorB
dtorA
start of programm
dtorC
dtorA
Why dtorB caled before start of programm?
Please help me to understand strange behavior:
I use dynamic_cast from MyObject to MyLogicObject when a destructor ~MyLogicObject() in processing, but compiler throw an exception: non_rtti_object.
I'm sure that object MyObject is a polymorph type. Where am I wrong?
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <string>
class A
{
int a;
};
class B
{
int b;
};
class MyObject: public A,
public B// if comment this row, and don't use multi inheritable, everything will be fine
{
private: std::string name;
private: bool singleshot;
public: MyObject(void);
public: virtual ~MyObject(void);
protected: void Destroying(void);
public: std::string GetName(void);
public: virtual bool Rename(std::string _newName);
};
#endif
#include "MyObject.h"
#include "MyLogicObject.h"
MyObject::MyObject(void): singleshot(true)
{}
MyObject::~MyObject(void)
{
printf("\n~my object\n");
Destroying();
}
void MyObject::Destroying(void)
{
if(singleshot)
{
printf("\nexception!\n");
dynamic_cast<MyLogicObject*>(this);// exception: non_rtti_object
singleshot = false;
}
}
std::string MyObject::GetName(void)
{
return name;
}
bool MyObject::Rename(std::string _newName)
{
name = _newName;
return true;
}
#ifndef MYLOGICOBJECT_H
#define MYLOGICOBJECT_H
#include "MyObject.h"
class MyLogicObject: public virtual MyObject // if not use virtual inheritance (instead, use the standard inheritance), everything will be fine
{
public: MyLogicObject(void);
public: virtual ~MyLogicObject(void);
public: virtual void Update(float _delta = 0.0f);
// if reimplement virtual method of base class, everything will be fine
/*
public: virtual bool Rename(std::string _newName)
{
return MyObject::Rename(_newName);
}
*/
};
#endif
#include "MyLogicObject.h"
MyLogicObject::MyLogicObject(void)
{}
MyLogicObject::~MyLogicObject(void)
{
printf("\n~my logic object\n");
Destroying();
}
void MyLogicObject::Update(float _delta)
{}
#include <conio.h>
#include <stdio.h>
#include "MyLogicScene.h"
class C
{
int c;
};
class DerivedObject: public MyLogicObject,
public C// if comment this row, and don't use multi inheritable, everything will be fine
{
public: DerivedObject(void)
{}
public: virtual ~DerivedObject(void)
{
printf("~derived object: %s\n", GetName().c_str());
//Destroying(); // if call Destroying in this place, overything will be file
}
};
int main()
{
DerivedObject* object1 = new DerivedObject();
object1->Rename("object1");
printf("delete object1...\n");
delete object1;
getch();
return 0;
}
You are trying to dynamic cast an object of a base class (MyObject) type to the derived class (MyLogicObject). And this conversion is not allowed with dynamic_cast unless the base class is polymorphic and rtti is enabled. See this for reference.
So you basically need to enable rtti in your compiler options.
Once that is done make sure that object1 is a complete object of the derived class (MyLogicObject) for the cast to work without raising an exception.
It would work in the opposite scenario too. If you were trying for example to dynamic cast an object of a derived class (MyLogicObject) type to the base class (MyObject).
I have the following class:
#include <string>
#include <stack>
#include <queue>
#include "map.h"
using namespace std;
#ifndef CONTAINER_H_
#define CONTAINER_H_
struct PathContainer {
int x, y;
string path;
};
class Container {
public:
virtual void AddTile(string, FloorTile *) = 0;
virtual void ClearContainer() = 0;
virtual PathContainer *NextTile() = 0;
};
class StackImpl : public Container {
private:
stack<PathContainer> cntr;
public:
StackImpl();
void AddTile(string, NeighborTile *);
void ClearContainer();
PathContainer *NextTile();
};
class QueueImpl : public Container {
private:
queue<PathContainer> cntr;
public:
QueueImpl();
void AddTile(string, NeighborTile *);
void ClearContainer();
PathContainer *NextTile();
};
#endif
When I try creating StackImpl or QueueImpl object like so:
Container *cntr;
cntr = new StackImpl();
or
Container *cntr;
cntr = new QueueImpl();
I get the following error at compile:
escape.cpp: In function ‘int main(int, char**)’:
escape.cpp:26: error: cannot allocate an object of abstract type ‘StackImpl’
container.h:23: note: because the following virtual functions are pure within ‘StackImpl’:
container.h:18: note: virtual void Container::AddTile(std::string, FloorTile*)
Any ideas?
typeid(NeighborTile *) != typeid(FloorTile *). The signatures differ, so they don't count as "the same" method even if NeighborTile inherits from FloorTile.