C++ Inheritance member functions using static variables - c++

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) {}
};

Related

Inheritance problem while changing variable value C++

What I'm trying to do is to change a variable from class A inside class B and make it the same in class C
class A
{
protected:
string name = "A";
};
class B: public A
{
protected:
string A::name="B";
};
class C: public B
{
// here i want "name" to be "B"
};
But the problem is, i'm getting an error in class C "illegal qualified name in member declaration".
You can't do it like this. If the field is being initialized in the base class, it is being initialized only in the base class. In other classes you can only change already initialized field.
One of the ways to do what you want can be passing the value in the constructor. So:
class A
{
public:
A(std::string initName = "A") : name(std::move(initName)) {}
protected:
string name;
};
class B: public A
{
public:
B() : A("B") {}
};
class C: public B
{
// name will be "B" here
};
what you want is to initialize the value of your variable in the constructor
public class B: public A
{
public:
B():name{"B"}{};
}
If the names of the classes are static and you don't mind using polymorphism, you could add a virtual member function returning the name of the class. Simply override the function in the derived classes to return a different name.
Example:
#include <iostream>
#include <memory>
#include <vector>
class A {
public:
virtual ~A() = default;
virtual const std::string& name() const {
static const std::string rv = "A";
return rv;
}
};
class B : public A {
public:
const std::string& name() const override {
static const std::string rv = "B";
return rv;
}
};
class C: public B {
// doesn't override name() - will be named "B"
};
int main() {
std::vector<std::unique_ptr<A>> objs; // Storage of base class pointers.
objs.emplace_back(std::make_unique<A>()); // Add pointers to...
objs.emplace_back(std::make_unique<B>()); // objects of different...
objs.emplace_back(std::make_unique<C>()); // derived classes.
// call the virtual member function through the base class pointer
for(auto& uptr : objs) {
std::cout << uptr->name() << '\n';
}
}
Output
A
B
B

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

Class variable in abstract base class or derived class?

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;
}

C++ : Calling inherited static method from static method

Consider the following abstract class AbstractEngine:
class AbstractEngine {
static void init();
static std::string getName();
};
And consider the following 2 implementor classes:
class Engine1 : public AbstractEngine {
static std::string getName();
};
class Engine2 : public AbstractEngine {
static std::string getName();
};
And, the init() function should call the correct getName() according to the type of class:
void AbstractEngine::init() {
std::cout << getName() << std::endl;
}
For example, If I call Engine1::init(), I would like it to call Engine1::getName() and not AbstractEngine::getName()
How can I make AbstractEngine::init() really to call the correct implementation of getName()?
You can use the CRTP, i.e. make AbstractEngine a template class, then when you inherit, inherit from AbstractEngine<EngineN>:
template <typename T>
class AbstractEngine {
public:
static void init() {
std::cout << T::getName() << std::endl;
}
};
class Engine1 : public AbstractEngine<Engine1> {
public:
static std::string getName() { return "Engine1"; }
};
class Engine2 : public AbstractEngine<Engine2> {
public:
static std::string getName() { return "Engine2"; }
};
Live Demo
If you also need some dynamic polymorphic behaviour, you can make a common non-template base class:
class AbstractEngine {
//I assume you would have some virtual functions here
};
template <typename T>
class AbstractEngineImpl : public AbstractEngine {
public:
static void init() {
std::cout << T::getName() << std::endl;
}
};
class Engine1 : public AbstractEngineImpl<Engine1> {
public:
static std::string getName() { return "Engine1"; }
};
class Engine2 : public AbstractEngineImpl<Engine2> {
public:
static std::string getName() { return "Engine2"; }
};
The getName() method should not be static. Neither the init() method.
You're trying to get polymorphic behaviour, but with static functions. This doesn't make any sense. By definition, polymorphic behaviour is associated with particular instance of objects - but static functions do not have an associated instance.
If you want polymorphic behaviour (as you tag suggests), consider this redesign:
class AbstractEngine {
virtual void init();
virtual std::string getName();
};
class Engine1 : public AbstractEngine {
std::string getName() override;
};
class Engine2 : public AbstractEngine {
std::string getName() override;
};

C++ unique static id and class name with base class

Having class TaskBase, each derived class of it must have name and unique id.
The TaskBase is something like below:
class TaskBase
{
public:
static const int id()
{
// return an unique id, for each object or derived class, HOW ??
}
static const string name()
{
// return class name for each derived class, HOW ??
// for example : "TaskBase" for this class
}
};
My try was :
template <typename DERIVED>
class TaskBase
{
public:
static const int id()
{
static const int id = reinterpret_cast<int> (typeid (DERIVED).name());
return id;
}
static const string name()
{
static string n;
if (!n.size())
{
int status;
char *realname = abi::__cxa_demangle(typeid (DERIVED).name(), 0, 0, &status);
n = realname;
free(realname);
}
return n;
}
};
I already read this, but i need the ability to have base pointer to each derived classes, something line below:
class MyTask1 : public TaskBase
{
};
MyTask1 myTask1, myTask2;
TaskBase *base = &myTask1;
class TaskBase
{
private:
const void* m_id;
string m_name;
public:
TaskBase(const void* m_id, string m_name): m_id(m_id), m_name(m_name)
{
}
const void* id() const
{
return m_id;
}
string name() const
{
return m_name;
};
};
template< typename DERIVED >
class TaskProxy: public TaskBase
{
public:
static const void* id()
{
//if you want to have for each object a unique id:
//return reinterpret_cast<void*>(this);
//just for each TaskProxy<????>:
return reinterpret_cast<const void*>(typeid( DERIVED ).name());
}
static string name()
{
return typeid( DERIVED ).name();
}
TaskProxy(): TaskBase(id(), name()) {}
};
Usage:
class MyTask1 : public TaskProxy< MyTask1 >
{
};
class MyTask2 : public TaskProxy< MyTask2 >
{
};
...
MyTask1 myTask1;
TaskBase *baseA = &myTask1;
MyTask2 myTask2;
TaskBase *baseB = &myTask2;
cout << "Name: " << baseA->name() << " Id:" << baseA->id() << endl;
cout << "Name: " << baseB->name() << " Id:" << baseB->id() << endl;
Which outputs this (with gcc 4.6):
Name: 7MyTask1 Id:0x401228
Name: 7MyTask2 Id:0x4011c0
I suggest implementing pure virtual methods for obtaining the class name and ID in the base class. The descendants would need to provide the unique names and IDs.
class TaskBase
{
public:
virtual std::string get_task_name(void) const = 0;
virtual unsigned long get_task_id(void) const = 0;
};
I took #VoidStar's suggest a step further and put the names into a (single) common class:
class TaskNames
{
protected:
static std::string get_tas1_name();
};
class Task1: public TaskBase, public TaskNames
{
//...
};
If you are following strictly standard C++, you may need to just bite the bullet and do some additional bookkeeping. Make an enum somewhere that stores all the classnames:
enum ClassID {
MYTASK1_CLASS,
MYTASK2_CLASS
};
It doesn't take that long to add a new classId when you make a new class.
I've done this before. It's sufficient for uniqueness to do what I describe above. But... if the enum values are set with a clever enough macro, you can encode the hierarchy of the classes, and implement dynamic cast and instanceof solely from the ClassID and a bitwise mask!