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...
Related
I have a class MyClass (with several virtual functions) that performs operations on an object called MyType.
The class MyClassImpl inherits MyClass and implements the virtual functions, but I need to add additional members to MyType, but I don't want to modify the class MyType (instead I want to keep it generic).
Now, if I make a MyTypeImpl and inherit MyType, I can add members. But, how do I make the non virtual functions in MyClassImpl (inherited from MyClass) use the new MyTypeImpl?
The only way I can think is to make MyClass use MyTypeImpl but I want to avoid using the implementation in the generic class because I might use various different implementations.
Here is a simple example of what the classes might look like. Of course, the code will not compile because the methods and members added in MyTypeImpl and not MyType.
class MyType {
public:
void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
class MyTypeImpl : public MyType {
public:
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClassImpl : public MyClass{
public:
void print() {
mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_.increment();
mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_.decrement();
mytype_.decrement();
};
};
After seeing your example I see now that you just want to extend the functionality of that class without modifying the original class. If you need to add additional functions, but you don't want to change the type that is stored in MyClass there isn't any way I know of to make that happen without at least modifying MyType to include virtual functions for the functions you want to call.
You also need to make MyClass take a pointer to MyType so you can use polymorphism and make the calls resolve to the correct implementation:
Dynamic Polymorphism Solution:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
// To be implemented by implementation class
virtual void print() = 0;
// To be implemented by implementation class
virtual void decrement() = 0;
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << 42 << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClass {
public:
MyClass(MyType* mytype)
: mytype_(mytype)
{}
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType* mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_->increment();
};
};
class MyClassImpl : public MyClass{
public:
MyClassImpl(MyType* mytype)
: MyClass(mytype)
{}
void print() {
mytype_->print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_->increment();
mytype_->increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_->decrement();
mytype_->decrement();
};
};
int main()
{
MyType* mytype = new MyTypeImpl();
MyClass* myclass = new MyClassImpl(mytype);
// Prints "42"
myclass->print();
// Do other stuff with "myclass"
delete myclass;
delete mytype;
}
Note, I am only using a raw pointer in this example for increased clarity. It is highly recommended that you don't use new and delete and use smart pointers to manage the lifetime of your pointers instead.
Static Polymorphism Solution:
Not that the design of this solution is actually any better, but I think this is closer to what you are actually looking for because it doesn't require modifying the MyType class directly. Also the only modification needed for MyClass is to make it a template class:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << data_ << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;
};
template <typename T>
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
T mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
template <typename T>
class MyClassImpl : public MyClass<T> {
public:
void print() {
this->mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
this->mytype_.increment();
this->mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
this->mytype_.decrement();
this->mytype_.decrement();
};
};
int main()
{
// Use the template to get the correct implementation
MyClassImpl<MyTypeImpl> myclass;
myclass.alg();
myclass.print();
// Do other stuff with my class
}
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).
Suppose I have code like that one, and I want to get access to the myClassB members. How can I do that? I need to use the functionality of functionA.
I can't change it because it is from the 3rd party library. And I need to use functionA to create it, and get values created by it. In this case "Test_1" string
class myClassA {
public:
myClassA(){}
~myClassA(){}
};
class myClassB : public myClassA
{
public:
myClassB(){}
void setString1(std::string newString)
std::string getS1()
private:
std::string privateMember;
};
std::shared_ptr<myClassA> functionA()
{
std::shared_ptr<myClassB> temporary(new myClassB());
temporary->setString1("TEST_1");
return std::move(temporary);
}
int main()
{
std::shared_ptr<myClassA> myPtr; // = functionA(); ??
}
Theoretically, you could use a dynamic_cast (or in this case specifically, std::dynamic_pointer_cast to get the derived pointer type. Like so:
std::shared_ptr<MyClassA> a_ptr = functionA();
std::shared_ptr<MyClassB> b_ptr = std::dynamic_pointer_cast<MyClassB>(a_ptr);
if(b_ptr) {//Check to verify the cast was successful
b_ptr->setString("Test1");
}
There is, however, a major caveat to this. In order for dynamic_cast (and therefore std::dynamic_pointer_cast) to work, your object hierarchy must have a virtual table defined. That means at least one of the methods defined by MyClassA must be declared virtual. The simplest solution is to declare the destructor virtual, since that's good practice whenever you're defining polymorphic objects (since you need it to ensure that any derived classes clean up their resources correctly).
class MyClassA {
public:
MyClassA() = default;
virtual ~MyClassA() = default;
};
Agree with dynamic_cast but without a virtual function table in ClassA, something like this would have to do:
Test This Code
#include <string>
#include <memory>
#include <iostream>
#include <set>
class myClassA {
public:
myClassA(){}
~myClassA(){}
};
class myClassB;
class ClassB_Registry{
private:
ClassB_Registry(){
}
~ClassB_Registry(){
}
public:
static ClassB_Registry* Get(){ static ClassB_Registry obj; return &obj; }
static void Register(myClassB* ptr){
Get()->mPointers.insert(ptr);
}
static void UnRegister(myClassB* ptr){
Get()->mPointers.erase(ptr);
}
static myClassB* Cast(myClassA* ptr){
if(Get()->mPointers.count((myClassB*)ptr) > 0) return (myClassB*)ptr;
return nullptr;
}
private:
std::set<myClassB*> mPointers;
};
class myClassB : public myClassA
{
public:
myClassB(){ ClassB_Registry::Register(this); }
~myClassB(){ ClassB_Registry::UnRegister(this); }
void setString1(std::string newString){privateMember = newString;}
std::string getS1() { return privateMember; }
private:
std::string privateMember;
};
std::shared_ptr<myClassA> functionA()
{
std::shared_ptr<myClassB> temporary(new myClassB());
temporary->setString1("TEST_1");
return std::move(temporary);
}
int main()
{
std::shared_ptr<myClassA> myPtr = functionA(); //??
std::shared_ptr<myClassA> myPtr_a(new myClassA()); //??
myClassB* pDerrived = ClassB_Registry::Cast(myPtr.get()); // bridge the RTTI gap
if(pDerrived)
std::cout << pDerrived->getS1();
pDerrived = ClassB_Registry::Cast(myPtr_a.get()); // works on A pointers to return null
if(pDerrived)
std::cout << pDerrived->getS1() << " \n";
else
std::cout << "Not A Pointer of Type B" << " \n";
}
It's not pretty, but if myClassB had a virtual table as mentioned previously, and all future derived classes used myClassB as the base, then you could bridge the gap for RTTI.
I have a code which has many derived class from a single base class. I wrote this code when there is minimum required and currently the specification changes so I need to create some 100+ derived classes.
My earlier implementation was something like
class Base {
public:
Base();
virtual ~Base();
virtual bool isThereError() { return false;}
virtual int configureMe() { return 0; }
virtual int executeMe() { return 0;}
};
class Derived_1 : public Base {
public:
Derived_1() {
errorStatus = false;
//Some initialization code for this class }
virtual ~Derived_1() {}
bool isThereError() { return errorStatus;}
int configureMe() {
// configuration code for this class
return 0;
}
int executeMe() {
//execute the major functionality of this class based on the configuration
return 0;
}
private:
bool errorStatus;
};
class Derived_2 : public Base {
public:
Derived_2() {
errorStatus = false;
//Some initialization code for this class }
virtual ~Derived_2() {}
bool isThereError() { return errorStatus;}
int configureMe() {
// configuration code for this class
return 0;
}
int executeMe() {
//execute the major functionality of this class based on the configuration
return 0;
}
private:
bool errorStatus;
};
Main.cpp:
#include "Base.h"
#include "Derived_1.h"
#include "Derived_2.h"
#include <set>
Derived_1 *dv1Ptr;
Derived_2 *dv2Ptr;
typedef std::set<Base *> ClassPtrList;
int main() {
ClassPtrList cpList;
dv1Ptr = new Derived_1();
dv2Ptr = new Derived_2();
dv1Ptr->configureMe();
if(dv1Ptr->isThereError()){
cpList.insert(dv1Ptr);
}
dv2Ptr->configureMe();
if(dv2Ptr->isThereError()){
cpList.insert(dv2Ptr);
}
while(true) {
for(ClassPtrList::iterator iter = cpList.begin(); iter != cpList.end(); ++iter) {
(*iter)->executeMe();
}
Sleep(1000);
}
}
I found the above implementation would lengthen the number of line and it is also not a good practice to write such a form of code when there are more derived classes. I need to write a code using MACRO or any other type, so that each derive class get instantiated by itself and the ClassPtrList keeps the pointer of all the derived class.
I started with something like,
#define CTOR_DERIVED(drvClass) return new drvClass()
but I'm not sure how to avoid creating pointer to update the list. I need to create 287 such derived classes.
Thanks in advance.
I am currently trying to deliver more than one implementation of an header file. I tried doing this like this:
// A.h:
class A {
public:
A();
~A();
bool method1();
bool method2();
}
// A.cpp:
A::A() {
}
A::~A() {
}
bool A::method1() {
}
bool A::method2() {
}
// B.h
class B : public A {
public B();
public ~B();
bool method1();
bool method2();
}
// B.cpp
B::B() {
}
B::~B() {
}
bool B::method1() {
// actual code I want to use
}
bool B::method2() {
// actual code I want to use
}
// AFactory.h
#define USE_B 10
#define USE_C 20
#define IMPL USE_B
class A;
class AFactory {
public:
static A *getImplementation();
}
// AFactory.cpp
A *AFactory::getImplementation() {
#if IMPL == USE_B
return new B();
#elif IMPL == USE_C
return new C();
#else
return NULL;
#endif
}
// Test.cpp
int main () {
A *test = AFactory::getImplementation();
test->method1();
test->method2();
}
The idea was, to deliver more than one implementation of the class A, which could be switched by simply changing the value of the define IMPL. The problem is, that the methods from the actual used implementation B are never called. The methods from the base class A are called instead. I tried to remove the A.cpp completly from the build, since it's never used or rather should never be used, but then it won't build, telling me, that I have undefined references in my test code.
If you want to override these methods, you use the virtual keyword.
class A
{
virtual bool method1();
}
class B : public A
{
virtual bool method1(); // If you want to override the base functionality.
}