Class variable in abstract base class or derived class? - c++

I have an abstract class that has a variable owner_ that is a string. Each derived class declares the name of this variable. Is it better practice to have the variable in the abstract base class, or can I better implement it multiple times in the derived class?
#include <string>
#include <iostream>
class Pet
{
public:
Pet(const std::string& owner) : owner_(owner) {}
virtual ~Pet() = 0;
virtual void print_status() = 0;
protected:
const std::string owner_;
};
Pet::~Pet() {}
class Dog : public Pet
{
public:
Dog(const std::string& owner) : Pet(owner) {}
~Dog() {};
void print_status()
{
std::string s = "Woof! My owner is ";
s += owner_;
std::cout << s << std::endl;
}
// Or better here?
// private:
// const std::string owner_;
};
class Cat : public Pet
{
public:
Cat(const std::string& owner) : Pet(owner) {}
~Cat() {};
void print_status()
{
std::string s = "Meow! My owner is ";
s += owner_;
std::cout << s << std::endl;
}
// Or better here?
// private:
// const std::string owner_;
};
int main()
{
Dog dog("Mario");
dog.print_status();
Cat cat("Luigi");
cat.print_status();
return 0;
}

IMO that's exactly what abstract base classes are for: Provide common implementations for an interface in an inheritance hierarchy.
I'd just go a step further and even separate the interface from the abstract base class:
struct IPet {
virtual ~IPet() = {}
virtual void print_status() = 0;
virtual const std::string& get_owner() const = 0;
};
class Pet : public IPet
{
public:
Pet(const std::string& owner) : owner_(owner) {}
virtual const std::string& get_owner() const { return owner_; }
virtual ~Pet() {} // = 0; Don't declare the destructor as pure virtual function
virtual void print_status() = 0;
protected:
std::string owner_;
};

You might want to use abstract to force your child classes to implement the method but not necessarily define anything in them. If you use them deliberately then having the owner in base class but different content in respective methods is correct.
Abstract methods are being used for example if you want all of your subclasses to at least declare the function inside their own class which is sometimes needed for the different behavior of respective subclass.
class Pet
{
public:
Pet(const std::string& owner) :
owner_(owner) {}
virtual ~Pet() = 0;
virtual void print_status() = 0;
protected:
const std::string owner_;
};
Pet::~Pet() {}
class Dog : public Pet
{
private:
int age;
public:
Dog(const std::string& owner, int age) :
Pet(owner), age(age) {}
~Dog() {};
void print_status(){
std::cout << "Woof! My owner is " << this->owner_ <<
" and my age is " << this->age << "\n\n";
}
};
class Cat : public Pet
{
public:
Cat(const std::string& owner) :
Pet(owner) {}
~Cat() {};
void print_status() {
std::cout << "Miaw, my owner is " << this->owner_ << '\n';
}
};
int main()
{
Dog dog("Mario", 25);
dog.print_status();
Cat cat("Luigi");
cat.print_status();
system("pause");
return 0;
}

Related

Why Decorator pattern works with pointers but not references?

I just learned about the decorator pattern and tried to write an example that uses the code. The example is about beverages and some condiments. Inside the Decorator I have a reference variable to a beverage. The beverages available are Decaf and Espresso. The condiments available are Soy and Caramel. If I define a Decaf with more than one Caramel for example, the result I get is just a Decaf with one decorator. So define Caramel->Caramel->Decaf gives me Caramel->Decaf. Defining Caramel->Soy->Caramel->Decaf works fine. Defining Caramel->Soy->Caramel->Caramel->Decaf gives me Caramel->Soy->Caramel->Decaf. Long story short, I can't have two or more condiments of the same type right one after the other. They become only one condiment. If I use pointers it works fine.
The code:
#include <iostream>
//#include "Decaf.h"
//#include "Espresso.h"
//#include "SoyDecorator.h"
//#include "CaramelDecorator.h"
class Beverage
{
public:
virtual std::string GetDescription() const = 0;
virtual int GetCost() const = 0;
};
class CondimentDecorator : public Beverage
{
public:
Beverage& beverage;
CondimentDecorator(Beverage& beverage) : beverage(beverage) {}
};
class Espresso : public Beverage
{
virtual std::string GetDescription() const override
{
return "Espresso";
}
virtual int GetCost() const override
{
return 5;
}
};
class Decaf : public Beverage
{
virtual std::string GetDescription() const override
{
return "Decaf";
}
virtual int GetCost() const override
{
return 4;
}
};
class CaramelDecorator : public CondimentDecorator
{
public:
CaramelDecorator(Beverage& beverage) : CondimentDecorator(beverage) {}
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Caramel";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 2;
}
};
class SoyDecorator : public CondimentDecorator
{
public:
SoyDecorator(Beverage& beverage) : CondimentDecorator(beverage) {}
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Soy";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 1;
}
};
int main()
{
Decaf d;
SoyDecorator s(d);
CaramelDecorator c(s);
CaramelDecorator cc(c);
std::cout << cc.GetDescription() << std::endl;
std::cout << cc.GetCost() << std::endl;
}
output:
Decaf with Soy with Caramel
7
// Expected:
// Decaf with Soy with Caramel with Caramel
// 9
Here is the same code but using pointers and works just fine:
https://ideone.com/7fpGSp
With switching from pointers to references, OPs constructor signature becomes very similar to the (default) copy constructor.
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
vs.
CondimentDecorator(const Beverage&); // generated by compiler
First, I assumed to delete the copy constructor would be sufficient but the compiler still tries to use the deleted constructor with a respective complaint as it cannot anymore.
Finally, I was able to fix OP's issue with providing the resp. candidates which prevent using the copy constructor.
(Deleting of copy constructor wasn't actually anymore needed but I left it in.)
class CondimentDecorator : public Beverage
{
public:
Beverage& beverage;
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
CondimentDecorator(CondimentDecorator &beverage) : beverage(beverage) {}
CondimentDecorator(const CondimentDecorator&) = delete;
};
The same has to be done for derived classes:
class CaramelDecorator : public CondimentDecorator
{
public:
CaramelDecorator(Beverage &beverage) : CondimentDecorator(beverage) {}
CaramelDecorator(CaramelDecorator &beverage) : CondimentDecorator(beverage) {}
//CaramelDecorator(const CaramelDecorator&) = delete;
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Caramel";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 2;
}
};
I fixed only the CaramelDecorator for demo but, actually, this has to be done for all derived classes of class CondimentDecorator.
The fixed MCVE of OP:
#include <iostream>
//#include "Decaf.h"
//#include "Espresso.h"
//#include "SoyDecorator.h"
//#include "CaramelDecorator.h"
class Beverage
{
public:
virtual std::string GetDescription() const = 0;
virtual int GetCost() const = 0;
};
class CondimentDecorator : public Beverage
{
public:
Beverage& beverage;
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
CondimentDecorator(CondimentDecorator &beverage) : beverage(beverage) {}
CondimentDecorator(const CondimentDecorator&) = delete;
};
class Espresso : public Beverage
{
virtual std::string GetDescription() const override
{
return "Espresso";
}
virtual int GetCost() const override
{
return 5;
}
};
class Decaf : public Beverage
{
virtual std::string GetDescription() const override
{
return "Decaf";
}
virtual int GetCost() const override
{
return 4;
}
};
class CaramelDecorator : public CondimentDecorator
{
public:
CaramelDecorator(Beverage &beverage) : CondimentDecorator(beverage) {}
CaramelDecorator(CaramelDecorator &beverage) : CondimentDecorator(beverage) {}
//CaramelDecorator(const CaramelDecorator&) = delete;
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Caramel";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 2;
}
};
class SoyDecorator : public CondimentDecorator
{
public:
SoyDecorator(Beverage &beverage) : CondimentDecorator(beverage) {}
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Soy";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 1;
}
};
int main()
{
Decaf d;
SoyDecorator s(d);
CaramelDecorator c(s);
CaramelDecorator cc(c);
std::cout << cc.GetDescription() << std::endl;
std::cout << cc.GetCost() << std::endl;
}
Output:
Decaf with Soy with Caramel with Caramel
9
Live Demo on coliru
Why the additional candidates are needed?
CondimentDecorator is derived from Beverage.
So, for:
CondimentDecorator d;
CondimentDecorator d2(d);
the compiler has two choices to construct d2:
the custom constructor CondimentDecorator::CondimentDecorator(Beverage &beverage)
the (default) copy constructor CondimentDecorator::CondimentDecorator(const CondimentDecorator&).
For the first, an implicit cast has to be applied but for the copy constructor, no cast is necessary (or at most, a const-cast).
Hence, the compiler prefers the copy constructor (unfortunately even, although it is deleted).
So, another candidate has to be provided which requires as less as implicit casts like the copy constructor:
another custom constructor CondimentDecorator::CondimentDecorator(CondimentDecorator&).
Further reading: Overload Resolution

Trying to edit static variable of parent A class for all child class B

I have a problem with a static variable within a class.
I'm trying to edit a static variable of a child class without editing the others childs class static variable.
The header file :
class A {
public:
A() {}
void printName() {qDebug() << _name; }
void changeName(QString name) {_name = name;}
private:
static QString _name;
};
QString A::_name = QString("default");
class B : public A {
public:
B() : A() {}
};
class C : public A {
public:
C() : A() {}
};
I'm trying to edit the static _name of my class B without editing the _name of my class C. When I try this code in this main.cpp :
int main(int argc, char *argv[])
{
A *a = new B{};
A *b = new B{};
A *c = new C{};
a->printName();
b->printName();
c->printName();
B *tmp = dynamic_cast<B*>(a);
tmp->changeName("new");
qDebug() << "Then";
a->printName();
b->printName();
c->printName();
}
Here's what I have :
"default"
"default"
"default"
Then
"new"
"new"
"new"
Anyone has any idea on how I could fix this ?
Here's what I've also try :
class A {
public:
A() {}
virtual ~A() {}
void printName() {qDebug() << _name; }
virtual void changeName(QString name) {_name = name;}
private:
static QString _name;
};
QString A::_name = QString("default");
class B : public A {
public:
B() : A() {}
void changeName(QString name) override {_name = name;}
private:
static QString _name;
};
class C : public A {
public:
C() : A() {}
void changeName(QString name) override {_name = name;}
private:
static QString _name;
};
There is only one A::_name, it can only have one value at any given time. Since all your derived types uses the same static member they necessarily all have the same _name value. To fix this, each derived type must provide it's own static member instead.
To avoid repeating the same members in every derived type, you can define them in a templated intermediate class that sits between A and the derived types B and C. Each template specialization has it's own static member. So, provided each derived type supplies a unique value to the intermediate type's template argument, they will have their own names. For example, split A into two classes :
#include <iostream>
#include <string>
class A {
public:
virtual void printName() = 0;
virtual void changeName(std::string name) = 0;
};
template<class T>
class A_impl : public A
{
public:
void printName() override {
std::cout << _name << '\n';
};
void changeName(std::string name) override {
_name = std::move(name);
};
private:
static std::string _name;
};
template<class T>
std::string A_impl<T>::_name = "default";
Then each derived type should inherit from A_impl instead of A. By providing their own type to A_impl, you can be sure each derived type provides a unique template argument :
class B : public A_impl<B> { };
class C : public A_impl<C> { };
Now your test should print
default
default
default
Then
new
new
default

C++ : calling an abstract base class constructor / undefined symbol in shared object

I am trying to use abstract classes and I met some problems when defining constructors of derived class. I wrote the following code, based on the answer to this question.
#include <string>
#include <iostream>
class ICommand {
private:
ICommand();
public:
const std::string name;
ICommand(const std::string& name) : name(name) { }
virtual void callMe();
virtual void callMe2();
};
class MyCommand : public ICommand {
public:
int x;
MyCommand(const std::string& name) : ICommand(name) { }
MyCommand(const std::string& name, int x) : ICommand(name), x(x) { }
void callMe() {
std::cout << name << "\n";
}
void callMe2() {
std::cout << name << x << "\n";
}
};
void f(std::string name) {
MyCommand A(name);
A.callMe();
}
This compiles without error. However my aim is to build a .so for a R package). In the R installation process, the .so is build without error, with clang++ -shared, but then there is a verification step which produces
unable to load shared object '/path/object.so':
/path/object.so: undefined symbol: _ZTI8ICommand
I've met this kind of problem before, and there are workarounds — not calling Icommand(name) is fairly simple, but I want to understand what is happening there, and, if possible, how to avoid the workaround.
Thanks in advance for your thoughts.
Answer
For the convenience of future readers: the only necessary change here is to replace the definition of virtual functions in the abstract class by
virtual void callMe() = 0;
virtual void callMe2() = 0;
which makes them pure virtual functions. Why this settles the problem totally beats me.
With the:
class MyClass {
private:
MyClass();
};
You are deleting a default constructor. If you want to call a default constructor then (declare or) define or don't define one but don't delete it. Your derived class default constructor will call the base class default constructor:
#include <string>
#include <iostream>
#include <memory>
class ICommand {
public:
std::string name;
ICommand() : name("The name") { std::cout << "Default base class constructor." << std::endl; }
virtual void callMe() = 0;
};
class MyCommand : public ICommand {
public:
MyCommand(){ std::cout << "Default derived class constructor." << std::endl; };
void callMe() override {
std::cout << name << std::endl;
}
};
void f2(const std::string& name) {
std::shared_ptr<ICommand> p = std::make_shared<MyCommand>();
p->callMe();
}
int main(){
f2("asdasd");
}
Part 2:
If you are trying to use the above classes in a polymorphic way then make your ICommand member functions pure virtual:
virtual void callMe() = 0;
virtual void callMe2() = 0;
Modify the void f function to:
void f(const std::string& name) {
std::shared_ptr<ICommand> p = std::make_shared<MyCommand>(name);
p->callMe();
}
Live example on Coliru.
class ICommand {
private:
ICommand() = default;
public:
const std::string name;
ICommand(const std::string& name) : name(name) { }
virtual ~ICommand() = default;
virtual void callMe() = 0;
virtual void callMe2() = 0;
};

C++ Inheritance member functions using static variables

I am trying to convert some Python classes into c++ but am having some trouble. I have a Base class which has a class (static) variable and a method which returns it. I also have a derived class which overrides the class (static) variable like so,
In Python:
class Base:
class_var = "Base"
#classmethod
def printClassVar(cls):
print cls.class_var
class Derived(Base):
class_var = "Derived"
d = Derived()
d.printClassVar()
which prints out the desired derived class variable, "Derived". Any idea how I can get the same functionality in c++? I have tried but end up getting the class variable of the Base class.
In c++
class Base
{
public:
static void printStaticVar(){cout << s_var << endl;}
static string s_var;
};
string Base::s_var = "Base";
class Derived : public Base
{
public:
static string s_var;
};
string Derived::s_var = "Derived";
void main()
{
Derived d;
d.printStaticVar();
}
Write a virtual function which returns a reference to the static member:
class Base
{
public:
void printStaticVar() {cout << get_string() << endl;}
static string s_var;
virtual string const& get_string() { return Base::s_var; }
};
string Base::s_var = "Base";
class Derived : public Base
{
public:
static string s_var;
virtual string const& get_string() { return Derived::s_var; }
};
string Derived::s_var = "Derived";
void main()
{
Derived d;
d.printStaticVar();
}
Note that printStaticVar shouldn't be static.
You could also make the string static local inside the getter:
class Base
{
public:
void printStaticVar() {cout << get_string() << endl;}
virtual string const& get_string() {
static string str = "Base";
return str;
}
};
class Derived : public Base
{
public:
virtual string const& get_string() {
static string str = "Derived";
return str;
}
};
void main()
{
Derived d;
d.printStaticVar();
}
Another possibility might be:
class Base
{
const std::string var;
public:
Base(std::string s="Base") : var(s) {}
void printVar() { std::cout << var << std::endl }
};
class Derived : public Base
{
public:
Derived(std::string s="Derived") : Base(s) {}
};

C++ virtual functions base return type suggestions

I need a base class that gives me primitive type of data's pointer. I add a function in it. I derived types of class. I used void * to support all primitive types as a return type but it is like old C days. It is not good for OOP. Does one have an suggestion to do in a proper way in OOP?
#include <iostream>
class base {
public:
virtual void *getPtr() = 0;
virtual ~base() {};
};
class derivedAType : public base {
protected:
int _i;
public:
derivedAType(int i): _i(0) { _i = i; };
virtual ~derivedAType() {}
virtual void *getPtr() {
return static_cast<void *>(&_i);
}
};
class derivedBType : public base {
protected:
short _s;
public:
derivedBType(short s): _s(0) { _s = s; };
virtual ~derivedBType() {}
virtual void *getPtr() {
return static_cast<void *>(&_s);
}
};
int main()
{
base *b1 = new derivedAType(1203912);
base *b2 = new derivedBType(25273);
std::cout << "b1 : " << *(static_cast<int *>(b1->getPtr()))
<< "\nb2 : " << *(static_cast<short *>(b2->getPtr()))
<< std::endl;
delete b2;
delete b1;
return 0;
}
Make the base class a template class with the data type as the template variable
template<typename DataType>
class base {
virtual DataType* getPtr() = 0;
//...
};
and
class derivedAType : public base<int>
But this changes base class to a template class which means you cant store them together, base<int> is different from base<short>
If this isnt acceptable, the other options is just a tad bit cleaner than your code but abt the same, refer to this question. Basically derived class return types can reflect their true type and i think it should get automatically converted to void*, so you dont have to manually cast the pointer.
Not sure about your problem. But maybe a double callback can help:
class Callback {
public:
virtual void do_int( int i ) const = 0;
virtual void do_short( short s ) const = 0;
/* ... */
}
class base {
public:
virtual void do_stuff(const Callback & c); /* will need a more telling name */
virtual ~base() {};
};
class derivedAType : public base {
protected:
int _i;
public:
derivedAType(int i): _i(0) { _i = i; };
virtual ~derivedAType() {}
virtual void do_stuff(const Callback & c) {
c.do_int( _i );
}
};
class derivedBType : public base {
protected:
short _s;
public:
derivedBType(short s): _s(0) { _s = s; };
virtual ~derivedBType() {}
virtual void do_stuff( const Callback & c) {
c.do_short( _s );
}
};
class print_callback : public Callback {
public:
virtual void do_int( int i ) const { std::cout << i; }
virtual void do_short( short s ) const { std::cout << s; }
}
int main() {
base *b1 = new derivedAType(1203912);
base *b2 = new derivedBType(25273);
std::cout << "b1 : ";
b1->do_stuff(print_callback());
std::cout << "\nb2 : ";
b2->do_stuff(print_callback());
std::cout << std::endl;
delete b2;
delete b1;
return 0;
}
Of course you can simplify this by just storing the created print callback, and using it twice.