Unit test noncopyable object - c++

I have a noncopyable monster base class, I also have a IView class.
I have a hobgoblin class that inherits from both monster an IView ,
I have a controller that takes a pointer to IView as a parameter.
Basically I want to check if hobgoblin exploded.
I'm using gmock / gtest
I keep getting
Actual function call count doesn't match EXPECT_CALL(h, Explode())...
Expected: to be called at least once
Actual: never called - unsatisfied and active
when i use the mock object. What am i missing?
Monster Base
#ifndef MONSTER_H
#define MONSTER_H
#include <string>
// interface for all monsters
class monster {
public:
virtual ~monster();
// forbid copying
monster(monster const &) = delete;
monster & operator=(monster const &) = delete;
void receive_damage(double damage);
void interact_with_chainsaw();
std::string name() const;
protected:
// allow construction for child classes only
monster();
private:
virtual void do_receive_damage(double damage) = 0;
virtual void do_interact_with_chainsaw() = 0;
virtual std::string do_name() const = 0;
};
#endif // MONSTER_H
IView
#ifndef IVIEW_H
#define IVIEW_H
class IView
{
public:
virtual void Explode() = 0;
virtual ~IView(){}
};
#endif // IVIEW_H
Hobgoblin
#ifndef HOBGOBLIN_H
#define HOBGOBLIN_H
#include "monster.h"
#include "iview.h"
class hobgoblin : public monster, public IView
{
public:
hobgoblin();
void Explode();
virtual ~hobgoblin();
private:
void do_receive_damage(double damage) final;
void do_interact_with_chainsaw() final;
std::string do_name() const final;
double health_;
};
#endif // HOBGOBLIN_H
#include "hobgoblin.h"
#include <QDebug>
hobgoblin::hobgoblin() :
health_(100.0)
{
}
hobgoblin::~hobgoblin()
{
}
void hobgoblin::Explode()
{
health_ = 0;
qDebug() << "Health is 0";
}
void hobgoblin::do_receive_damage(double damage)
{
health_ -= damage;
}
void hobgoblin::do_interact_with_chainsaw()
{
// imagine horrible, gory things here such as
// having to deal with a singleton
}
std::string hobgoblin::do_name() const
{
static std::string const name("Furry hobgoblin of nitwittery +5");
return name;
}
Controller
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include "iview.h"
class Controller
{
public:
Controller(IView *view);
void Explode();
~Controller();
private:
IView *m_View;
};
#endif // CONTROLLER_H
#include "controller.h"
#include <QDebug>
Controller::Controller(IView *view):
m_View(view)
{
}
void Controller::Explode()
{
m_View->Explode();
}
Controller::~Controller()
{
}
Unit Test
class mockmonster : public IView
{
public:
MOCK_METHOD0(Explode,void());
virtual ~mockmonster(){}
};
TEST(MockMonster,Explode)
{
// this is not calling explode as expected.
mockmonster h;
Controller c(&h);
c.Explode();
}
TEST(HobGoblin,Explode)
{
// this calls explode fine
hobgoblin h;
Controller c(&h);
c.Explode();
}

Well, shouldn't your Explode function be virtual?
By the looks of it, your mockmonster is shadowing IView's function. Since Controller is taking a pointer to IView, and Explode is non-virtual, it will invoke IView's version.
As a side-note, I doubt if either of your classes being non-copyable matters here. When using gmock, non-copyable classes are problematic when setting up expectations/assertions (i.e. you expect a function to be called with a specific object - this object would have to be copied internally by gmock, and that might fail).

Related

Avoiding repetitive sub-class definitions in C++

I am new to C++ classes, and I have a question about defining multiple sub-classes of an abstract type/interface which would have identical definitions.
Take the following example which might appear in a header file with 3 sub-classes:
class Animal {
private:
int a;
int b;
public:
explicit Animal(int a) {}
virtual Animal* getFriend() = 0;
virtual bool walk() = 0;
virtual bool talk() = 0;
virtual bool someFunction() = 0;
virtual bool someOtherFunction() = 0;
// ... many more functions
}
class Zebra: public Animal {
Animal* getFriend();
bool walk();
bool someFunction();
bool someOtherFunction();
// ... continues for many more functions
}
class Cow: public Animal {
Animal* getFriend();
bool walk();
bool someFunction();
bool someOtherFunction();
// ... continues for many more functions
}
class Salmon: public Animal {
Animal* getFriend();
bool walk();
bool someFunction();
bool someOtherFunction();
// ... continues for many more functions
}
// ... many more animals
Declaring the sub-classes like this seems repetitive and potentially error prone. Because the class definitions are identical except for the name of the class, is there a more efficient way to declare the animal sub-classes in bulk?
In the context I am working in each animal would have a completely independent implementation in separate .cpp files.
Please let me know if i'm approaching this completely wrong. Any help would be greatly appreciated.
It is indeed error prone when you don't make use of the override keyword for each overridden virtual class member function.
Instead of declaring the derived class function like this
bool someFunction();
you can/should declare it like this
bool someFunction() override;
In this way, you would get a compilation error if the declaration doesn't match the base class signature. Without it, you would have a perfectly good compilable program but with a behaviour bug.
Other than that, your strategy is fine, and is the way to do handle abstract functions.
I'm writing another answer as an alternative solution. Actually, If i faced with same 'issue' or 'problem', i would not declare as bulk, I would just create zebra.h, zebra.cpp, inherits from Animal and declare/define all members individually. In other words i would prefer not to be clever but if you want to be the piece of codes below could be an alternative.
Indeed, you just want to create a class declaration from a template. That's what template is doing. It is possible to mimic same behaviour with MACROs but I would prefer template rather than MACRO because it is what Bjarne did.
So here is the code
animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
class Animal {
private:
int a;
int b;
public:
explicit Animal(int a) {}
virtual ~Animal() = default; // You should this virtual destructor
// for polymorphic types.
virtual Animal* getFriend() = 0;
virtual bool walk() = 0;
virtual bool talk() = 0;
virtual bool someFunction() = 0;
virtual bool someOtherFunction() = 0;
};
enum class animal_types
{
zebra ,
cow ,
salmon ,
special_animal
};
template< animal_types >
struct ugly_bulk_animal_inheritor : Animal
{
using Animal::Animal; // Use parent constructor as is
Animal* getFriend() override;
bool walk() override;
bool talk() override;
bool someFunction() override;
bool someOtherFunction() override;
};
using Zebra = ugly_bulk_animal_inheritor< animal_types::zebra >;
using Cow = ugly_bulk_animal_inheritor< animal_types::cow >;
using Salmon = ugly_bulk_animal_inheritor< animal_types::salmon >;
// So on..
#include "zebra.h"
#include "salmon.h"
#include "cow.h"
#include "special_animal.h"
#endif // ANIMAL_H
cow.h
#ifndef COW_H
#define COW_H
#include "animal.h"
template<>
Animal* Cow::getFriend() {
return nullptr;
}
template<>
bool Cow::walk() {
return true;
}
template<>
bool Cow::talk() {
return false;
}
template<>
bool Cow::someFunction() {
return true;
}
template<>
bool Cow::someOtherFunction() {
return true;
}
#endif // COW_H
salmon.h
#ifndef SALMON_H
#define SALMON_H
#include "animal.h"
template<>
Animal* Salmon::getFriend() {
return nullptr;
}
template<>
bool Salmon::walk() {
return true;
}
template<>
bool Salmon::talk() {
return true;
}
template<>
bool Salmon::someFunction() {
return true;
}
template<>
bool Salmon::someOtherFunction() {
return true;
}
#endif // SALMON_H
zebra.h
#ifndef ZEBRA_H
#define ZEBRA_H
#include "animal.h"
template<>
Animal* Zebra::getFriend() {
return nullptr;
}
template<>
bool Zebra::walk() {
return true;
}
template<>
bool Zebra::talk() {
return false;
}
template<>
bool Zebra::someFunction() {
return true;
}
template<>
bool Zebra::someOtherFunction() {
return true;
}
#endif // ZEBRA_H
special_animal.h
#ifndef SPECIAL_ANIMAL_H
#define SPECIAL_ANIMAL_H
#include "animal.h"
#include <iostream>
template<>
struct ugly_bulk_animal_inheritor<animal_types::special_animal> : Animal
{
using Animal::Animal; // Use parent constructor as is
Animal* getFriend() override { return nullptr; }
bool walk() override { return true; }
bool talk() override { return true; }
bool someFunction() override { return true; }
bool someOtherFunction() override { return true; }
void specility_fn() {
std::cout << "A speciality" << std::endl;
}
private:
int some_extra_member;
// etc..
};
using special_animal = ugly_bulk_animal_inheritor<animal_types::special_animal>;
#endif // SPECIAL_ANIMAL_H
main.cpp
#include <iostream>
#include "animal.h"
int main(int argc, char *argv[])
{
Animal* instance;
Zebra z { 5 };
Cow c { 6 };
Salmon t { 7 };
instance = &z;
std::cout << "Zebra can talk ? " << instance->talk() << std::endl;
instance = &t;
std::cout << "Salmon can talk ? " << instance->talk() << std::endl;
special_animal s { 5 };
s.specility_fn();
return 0;
}
Short of using a macro to define the classes (which is even worse!), there probably isn't a great deal you can do. Occasionally stuff like this might work, but I'd wager that at some point, you'd want to specialise one of the animals, leading to you ditching the macro again. It's for that reason I'd avoid that particular technique.
#define DECLARE_ANIMAL(ANIMAL_TYPE) \
class ANIMAL_TYPE: public Animal { \
Animal* getFriend() override; \
bool walk() override; \
bool someFunction() override; \
bool someOtherFunction() override; \
};
DECLARE_ANIMAL(Zebra);
DECLARE_ANIMAL(Cow);
DECLARE_ANIMAL(Salmon);
Generally speaking, try to move as much of the duplicated class methods & data into the base class to minimise the amount of code duplication. This may require a slight change in the way you think about the problem though....
For example, walk(). In the case of a Cow/Zebra/Horse/Cat/Dog, the act of walking is pretty much identical. The only real differences can be measured with data (e.g. the walk speed, how many legs are used, what is the gait of the walk, how large is each stride?). If you can define the behaviour in a data-driven fashion, you would just need to set those parameters in the Derived class constructor, and avoid the need for
customised methods. Approaching the class design this way has a few other benefits, for example you'd have a single 'Dog' class, but it would be able to represent a 4 legged dog, and a 3 legged dog, without needing to create a new class.
That's usually the approach I'd recommend anyway...

Error"pure virtual method called",when this method has been override

I'm trying to practice "Observer Design Pattern". When I thought a abstract's pure virtual method has been override by it's derived class, a error occurred.
There is a observer which is an abstract class in a independent file:
#ifndef DESIGN_PATTERNS_OBSERVER_H
#define DESIGN_PATTERNS_OBSERVER_H
#include "subject.h"
class Subject;
class Observer{
protected:
Observer();
public:
virtual ~Observer();
virtual void update(Subject *the_changed_subject) = 0;
};
Observer::Observer() {}
Observer::~Observer() {}
#endif //DESIGN_PATTERNS_OBSERVER_H
Observer defined a pure virtual method "update" which overrides as follow:
#ifndef DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#define DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#include <iostream>
#include "observer.h"
#include "concrete_subject.h"
class ConcreteObserver : public Observer{
public:
void update(Subject *the_changed_subject) override {
auto cs = dynamic_cast<ConcreteSubject *>(the_changed_subject);
std::cout << "status changed to " << cs->get_status() << std::endl;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_OBSERVER_H
And also there is a subject which is an abstract class too.The error "pure virtual method called" happened in "notify" method where I had marked.
From debug, it seems "notify" uses Observer's "update" rather than ConcreteObserver's.
However,in main function the _observers should stored pointers of ConcreteObservers which override "update".
#ifndef DESIGN_PATTERNS_SUBJECT_H
#define DESIGN_PATTERNS_SUBJECT_H
#include <list>
#include "observer.h"
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
#endif //DESIGN_PATTERNS_SUBJECT_H
And it has a derived class "ConcreteSubject":
#ifndef DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#define DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#include "subject.h"
class ConcreteSubject : public Subject {
private:
int status;
public:
ConcreteSubject() {
status = 0;
}
void set_status(int s) {
this->status = s;
Subject::notify();
}
int get_status() {
return status;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_SUBJECT_H
The main function:
#include <iostream>
#include <vector>
#include "singleton.h"
#include "observer/concrete_subject.h"
#include "observer/concrete_observer.h"
void test2() {
ConcreteSubject concreteSubject;
std::vector<ConcreteObserver> observers;
for (int i = 0; i < 5; ++i) {
ConcreteObserver observer = ConcreteObserver();
concreteSubject.attach(&observer);
observers.push_back(observer);
}
concreteSubject.set_status(2);
}
int main() {
test2();
return 0;
}
As I mentioned before, the _observers of ConcreteSubject's super class Subject should stored pointers of ConcreteObservers which override "update" already.
I don't understand why Observer's "update" still called.
Here is another strange thing.I make a small test has almost the same relationship of classes I showed.But no error occured.
class ABaseA{
public:
virtual void do_some() = 0;
};
class MidA : public ABaseA{
public:
void do_some() override {
cout << "real do some" << endl;
}
};
class ABaseB{
private:
list<ABaseA*> *bases;
public:
ABaseB() {
bases = new list<ABaseA*>();
}
virtual ~ABaseB() = default;
virtual void add(ABaseA* item) {
bases->push_back(item);
}
virtual void do_active() {
for(ABaseA *p : *bases) {
p->do_some();
}
}
};
class MidB : public ABaseB{
public:
MidB() = default;
void active() {
ABaseB::do_active();
}
};
void test3() {
MidA midA;
MidB midB;
midB.add(&midA);
midB.active();
}
The only difference is this code is in one file.
In the file of Subject.h you should be transfer below code to Subject.cpp:
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
Also you should be add class Observer; in top of Subject.h
#include <list>
#include "Observer.h"
class Observer; //you should be add this line
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};

Requiring derived class to define a method

I am no doubt overlooking something basic but my implementation is obviously flawed.
I am trying to require a derived classes to implement a method being called in a base class.
class IClock
{
public:
virtual void OnTimeExpired() = 0;
}
class Clock : public IClock
{
... // ABC not implemented
}
class Application : public Clock
{
... // ABC not implemented
}
class DerivedApp : public Application
{
public:
virtual void OnTimeExpired() { ... }
}
I rarely use pure ABCs, so I thought by not defining the pure virtual method in Clock and Application, it would require all derivatives of Application to define the OnTimeExpired() method.
I discovered this will compile and link (MSVS-2017) and if DerivedApp does not implement the method, the Clock object will call an undefined method and crash.
Why does this compile without the pure virtual method being implemented?
How do I force derived Application classes to implement the OnTimeExpired() method?
EDIT: The crash was due to unrelated error - I apologize. Nevertheless the questions I ask are still applicable.
As requested here is a complete, buildable, minimal example:
IClock.h:
#pragma once
class IClock
{
public:
virtual void OnClockTime() = 0;
};
Clock.h:
#pragma once
#include "IClock.h"
class Clock : public IClock
{
public:
Clock();
virtual ~Clock();
void ClockUpdate();
virtual void OnClockTime();
private:
float elapsed_time;
};
Clock.cpp:
#include "Clock.h"
Clock::Clock()
: elapsed_time(0.0f)
{
}
Clock::~Clock()
{
}
void Clock::ClockUpdate()
{
elapsed_time += 0.0000001f; // small ticks for testing
if (elapsed_time >= 1.0f) {
OnClockTime();
elapsed_time -= 1.0f;
}
}
void Clock::OnClockTime()
{}
ApplicationBase.h
#pragma once
#include "Clock.h"
class ApplicationBase : public Clock
{
public:
ApplicationBase();
virtual ~ApplicationBase();
virtual void Init(){}
virtual void Run(){}
protected:
bool app_run;
};
ApplicationBase.cpp:
#include "ApplicationBase.h"
ApplicationBase::ApplicationBase()
: app_run(false)
{
}
ApplicationBase::~ApplicationBase()
{
}
DerivedApp.h:
#pragma once
#include "ApplicationBase.h"
class DerivedApp : public ApplicationBase
{
public:
DerivedApp();
virtual ~DerivedApp();
virtual void Init() {}
virtual void Run();
//virtual void OnClockTime();
};
DerivedApp.cpp:
#include "DerivedApp.h"
#include <iostream>
DerivedApp::DerivedApp()
{
}
DerivedApp::~DerivedApp()
{
}
void DerivedApp::Run()
{
app_run = true;
while (app_run) {
ClockUpdate();
}
}
//void DerivedApp::OnClockTime()
//{
// static int counts(0);
// std::cout << "Tick..." << std::endl;
// counts++;
// if (counts >= 10)
// app_run = false;
//}
main.cpp
#include "DerivedApp.h"
class App : public DerivedApp
{
public:
App(){}
~App(){}
};
int wmain(int argc, wchar_t * argv[])
{
App *app = new App();
app->Init();
app->Run();
delete app;
}
Thanks to those who requested a minimal working example, I built it and it works exactly as I had hoped. The complier will complain about no instantiation of the ABC in the App class. If I remove the comments from DerivedApp::OnClockTime() it compiles and runs the way I wish. Obviously my actual code is not following this model as I thought, so now I need to reexamine where I went wrong. Thanks.
There is no keyword in C++ that forces a class to override some method. However, by making OnTimeExpired() pure virtual you're making IClock an abstract class. Any classes deriving from IClock that do not implement OnTimeExpired() will automatically become an abstract class too, thus not allowing you to create objects of these classes. This means that your code as-is is completely legal unless you try to make objects of these classes
class AbstractBase {
public:
virtual void someFunc() = 0; // Purely Virtual
};
class AbstractDerived : public AbstractBase {
public:
void someOtherFunc();
// Still abstract because the following is not declared-defined
// void someFunc() override { ... }
};
class NonAbstractDerivedA : public AbstractBase { // Derived From Base
public:
void someFunc() override { /* do this class's implementation*/ }
};
class NonAbstractDerivedB : public AbstractDerived { // Derived From AbstractDerived
public:
void someFunc() override { /* do this class's implementation*/ }
};
uses:
#include "above"
int main() {
AbstractBase base; // compiler error
AbstractDerived derived; // compiler error
NonAbstractDerivedA derivedA; // should be okay
NonAbstractDerivedB derivedB; // should be okay
return 0;
}

C++, Googlemock - testing local object

I started to use googletest and googlemock libraries and I have a problem which I cannot solve. I have a code something like this:
class Painter
{
public:
void DrawSomething();
};
void Painter::DrawSomething()
{
Turtle turtle;
turtle.doSomething();
}
main()
{
Painter p;
p.DrawSomething();
}
I have mocked the Turtle class but how can I test doSomething() method (for example with EXPECT_CALL) when the object of turtle is created locally? Is it possible without modifying Painter class?
Thank you for answers.
I have mocked the Turtle class ...
How exactly did you mock it?
... but how can I test doSomething() method (for example with EXPECT_CALL) when the object of turtle is created locally?
Is it possible without modifying Painter class?
(Emphasis mine)
The straightforward answer is: No.
You cannot magically inject a mock instead of a real instance used in another class without decoupling via an interface.
You should have something like the following code instead:
struct ITurtle {
virtual void PenUp() = 0;
virtual void PenDown() = 0;
virtual void TurnLeft(double degrees) = 0;
virtual void Move(double distance) = 0;
// ...
virtual ~ITurtle() {}
};
struct TurtleMock : ITurtle {
// Mock method declarations
MOCK_METHOD0(PenUp, void ());
MOCK_METHOD0(PenDown, void ());
MOCK_METHOD1(TurnLeft, void (double));
MOCK_METHOD1(Move, void (double));
};
class Turtle : public ITurtle {
public:
void PenUp();
void PenDown();
void TurnLeft(double degrees);
void Move(double distance);
};
Provide the real implementation for the above declarations in a separate translation unit.
class Painter {
public:
Painter(ITurtle& turtle) : turtle_(turtle) {}
void DrawSomething();
private:
ITurtle& turtle_;
};
void Painter::DrawSomething() {
turtle_.PenDown();
turtle_.TurnLeft(30.0);
turtle_.Move(10.0);
turtle_.TurnLeft(30.0);
turtle_.Move(10.0);
// ...
}
You can alternatively pass the ITurtle interface to the DrawSomething() function:
class Painter {
public:
void DrawSomething(ITurtle& turtle);
};
void Painter::DrawSomething(ITurtle& turtle) {
turtle.PenDown();
turtle.TurnLeft(30.0);
turtle.Move(10.0);
turtle.TurnLeft(30.0);
turtle.Move(10.0);
// ...
}
int main() {
NiceMock<TurtleMock> turtle;
Painter p(turtle);
// Painter p; <<< for the alternative solution
EXPECT_CALL(turtle,PenDown())
.Times(1);
EXPECT_CALL(turtle,TurnLeft(_))
.Times(2);
EXPECT_CALL(turtle,Move(_))
.Times(2);
p.DrawSomething();
// p.DrawSomething(turtle); <<< for the alternative solution
}
I have written a wrapper class to mock production code without changing it. Please let me know if there is any flaw in this.
#include "gtest/gtest.h"
#include "src/gtest-all.cc"
#include "src/gmock-all.cc"
#include "src/gmock_main.cc"
#include <iostream>
#include <string>
#include <vector>
using ::testing::An;
using ::testing::AtLeast;
using ::testing::DoAll;
using ::testing::NotNull;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::SetArgReferee;
using namespace std;
class Student
{
int iAge;
public:
Student(int _iAge) : iAge(_iAge)
{
}
virtual void PrintDetails()
{
cout<<"Age:"<<iAge<<endl;
}
virtual bool CheckGrade(int iGrade)
{
return (iGrade - 5) == iAge;
}
};
class StudentFaker
{
static Student* internalObject;
public:
static void FakerSetObject(Student* object) {
internalObject = object;
}
StudentFaker(int _iAge){
}
void PrintDetails() {
internalObject->PrintDetails();
}
bool CheckGrade(int iGrade) {
return internalObject->CheckGrade(iGrade);
}
};
Student* StudentFaker::internalObject = NULL;
class StudentMock : public Student
{
public:
StudentMock(int _iAge) : Student(_iAge) { }
MOCK_METHOD0(PrintDetails,void());
MOCK_METHOD1(CheckGrade,bool(int));
};
#define UNITTEST
bool ProductionCode();
TEST(STUDENT,TEST)
{
StudentMock stMock(8);
EXPECT_CALL(stMock, PrintDetails())
.Times(AtLeast(1))
.WillOnce(Return());
EXPECT_CALL(stMock, CheckGrade(5))
.Times(AtLeast(1))
.WillOnce(Return(true));
StudentFaker::FakerSetObject(&stMock);
EXPECT_TRUE(ProductionCode());
}
//Production code
#ifdef UNITTEST
#define Student StudentFaker
#endif
bool ProductionCode()
{
Student st(8);
st.PrintDetails();
if(st.CheckGrade(5))
return true;
else
return false;
}
//Production code

C++ dynamic_cast exception

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).