I am trying to do this:
class Parameter
{
public:
Parameter(){};
~Parameter(){};
};
class Address : public Parameter
{
public:
Address(uint16_t val) : value(val){};
Address(const Address& b) : value(b.value){};
~Address(){};
private:
uint16_t value;
};
class Constant : public Parameter
{
public:
Constant(int val) : value(val){};
Constant(const Constant& b) : value(b.value){};
~Constant(){};
private:
int value;
};
How can I add set and get methods for the parent class Parameter so that when I create a Constant or Address object, I can use the parent methods to set and get the variable value?
Not sure what you meant, but here is a try:
template <typename T>
class Parameter
{
public:
const T& getValue() { return value; }
protected:
T value;
};
class Address : public Parameter<uint16_t>
{
public:
Address() { value = 2154; }
// ...
}
class Name : public Parameter<std::string>
{
public:
Name() { value = "John Doe"; }
// ...
}
Later you can do:
Address address;
Name name;
cout << name.getValue() << " lives at house no " << address.getValue();
// outputs "John Doe lives at house no 2154".
You could implement it as a pure virtual function and over ride it in the below classes?
Related
I have a class that is called Object, this class's header is:
class DLL_SPEC Object {
public:
Object();
virtual ~Object();
virtual std::string getString() const;
virtual void setString(std::string value);
virtual int getInt() const;
virtual void setInt(int value);
virtual double getDouble() const;
virtual void setDouble(double value);
virtual bool isType(FieldType type) const;
};
And my child classes are as follows:
class DLL_SPEC IntObject : public Object {
public:
IntObject() : value(0) {}
IntObject(int v) : value(v) {}
void setInt(int value) override { this->value = value; };
int getInt() const override { return this->value; };
bool isType(FieldType type) const override;
private:
int value;
};
class DLL_SPEC DoubleObject : public Object {
public:
DoubleObject() : value(0.0) {}
DoubleObject(double v) : value(v) {}
void setDouble(double value) override { this->value = value; };
double getDouble() const override { return this->value; };
bool isType(FieldType type) const override;
private:
double value;
};
class DLL_SPEC StringObject : public Object {
public:
StringObject() : value("") {}
StringObject(std::string v) : value(v) {}
void setString(std::string value) override { this->value = value; };
std::string getString() const override { return value; };
bool isType(FieldType type) const override;
private:
std::string value;
};
Now, the problem is, I have an array of Objects and I want to get a string representation of a StringObject.
I call array[0].getString() and even though the object is of type StringObject, the method that gets called is the one is the base class, which I understand.
So, how would I go about implementing that whenever I call getString() on the base class it goes to the child one of the SAME object?
I've tried using this method:
std::string Object::getString() const
{
return dynamic_cast<StringObject*>(this).getString();
}
but then I get an error stating I cannot cast away const or any type qualifier, which is fixed by deleting const modifier (which I MUST leave there as it's according to the task), but then I get another one stating that no suitable constructor exists. So how would I go about implementing this and getting this base class to use the one of the child one?
EDIT: Added a small example that goes into the getString method of Object class and not the StringObject class.
int findPersonId(std::string whereName)
{
Db* db = Db::open("database");
Table* people = db->openTable("table");
auto iteratorTable = table->select();
while (iteratorTable->moveNext())
{
for (size_t i = 0; i < table->getFieldCount(); i++)
{
if (table->getFields()[i]->getName() == "id")
{ //this one beneath goes to the base class and not StringObject
std::string foundRow = iteratorPeople->getRow()[i]->getString();
if (foundRow == whereName)
{
return iteratorTable->getRowId();
}
}
}
}
return 0;
}
Note: The Table* is 2D array that consists of Object** (array that contains StringObject, IntObject, DoubleObject). The method .getRow() return the Object** array that consists of StringObject ...
The way I initiate the objects that go into the array is
Table* table= db->openOrCreateTable("table", 2, userFields); //this creates a 2d array
StringObject* name = new StringObject("Joseph");
IntObject* id = new IntObject(5);
Object** row = combineToRow(id, name);
table->insert(row); //insert an array into 2D array
The method combineToRow is just a simple convertor to Object**.
template<typename A, typename B>
Object** combineToRow(A a, B b) {
return new Object * [2]{ a, b };
}
You have not implemented a getString method for your IntObject, and since you didn't override it you are calling the base method. Once you implement it like this
class IntObject : public Object {
...
virtual std::string getString() const { return std::to_string(value); };
...
};
then you can call it.
int main(){
StringObject* name = new StringObject("Joseph");
IntObject* id = new IntObject(5);
Object** row = combineToRow(id, name);
std::cout << row[0]->getString() << " " << row[1]->getString();
}
5 Joseph
See working version here
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
What I'm trying to achieve is to keep track of what types of objects we're created that inherit from a base class. If a class inherits from the base class but is not instantiated in an object I'm not that interested in tracking that (this condition can be included or not depending if the implementation is easier or not)
Dummy example:
template <typename T>
class Person
{
public:
Person() {
T* x;
container.push_back(x);
}
virtual ~Person() {}
private:
static heterogeneous_container container;
};
class Employee : public Person <Employee>
{
};
class Employee2 : public Employee
{
};
Also, I would like this to work for chained inheritance. Is it possible that when I instantiate an Employee2, the base class Person will add an Employee2 type pointer in the container?
As for the heterogeneous container, I think this can be used link
I think what you want is more like:
class Person
{
public:
Person() {
objects.push_back(this);
}
virtual ~Person() {
objects.erase(this);
}
private:
static std::set<const Person*> objects;
};
class Employee : public Person
{
};
class Employee2 : public Employee
{
};
With this approach, you can enquire the dynamic type of the most-derived object that each of the pointers in the container points to.
Note that the objects set has to contain the pointers, not the type_info for each object. The problem is that inside the constructor for the Person sub-object of an Employee2 object, the most-derived type of *this will be Person, not Employee2 (it won't become Employee2 until execution enters the Employee2 constructor).
More or less, I have somewhere working like that :
#include <iostream>
#include <functional>
#include <vector>
struct ClassEntry {
size_t id = 0;
const char* label;
};
class BaseClass {
public:
protected:
static void RegisterType(size_t id, const char * label) {
ClassEntry entry;
entry.id = id;
entry.label = label;
mRegisteredTypes.emplace_back(entry);
std::cout << "Registered type " << id << " label " << label << std::endl;
}
static size_t createId() {
static size_t id = 0;
return id++;
}
static std::vector<ClassEntry> mRegisteredTypes;
};
std::vector<ClassEntry> BaseClass::mRegisteredTypes;
class OneTimeCall {
public:
OneTimeCall(std::function<void(void)>&& func) {
func();
}
virtual ~OneTimeCall() {
}
};
template<typename T>
class MyClass : public BaseClass {
public:
MyClass() {
static OneTimeCall one_time {
[this]{
BaseClass::RegisterType(GetId(), T::GetType());
}
};
}
private:
protected:
static size_t GetId() {
static size_t id = BaseClass::createId();
return id;
}
};
class A : public MyClass<A> {
public:
A() {
}
static const char *GetType() {
return "ClassA";
}
};
class B : public MyClass<B> {
public:
B() {
}
static const char *GetType() {
return "ClassB";
}
};
int main() {
A a;
B b;
A a2;
B b2;
return 0;
}
The output is :
Registered type 0 label ClassA
Registered type 1 label ClassB
The main idea is to use CRTP and static initialization in construction for register each type only one time. It works without problems in linux, on windows compiler the static BaseClass ID is new on each DLL, so you need to tune a bit for use in a external library.
With this approach you dont need any external library and is possible to compile without rtti.
For inheritance you can create a new class:
template<typename Current, typename Base>
class Mix : public MyClass<Current>, public Base {};
So if you pass "type C" as current type (CRTP) and type A as base class can work.
class C : public Mix<C, A> {
public:
C() {
}
static const char *GetType() {
return "ClassC";
}
};
With this approach if you have previously registered "A" it will not be registered again, and if you dont have "A" it will be registered after "C".
One way to track objects is to store them an intrusive list and embed a link node into the objects. This provides noexcept guarantee for tracker operations and doesn't require an extra memory allocation when inserting the elements into the tracker container, for the price of an embedded list node (two pointers) in each tracked object:
#include <iostream>
#include <boost/intrusive/list.hpp>
namespace bi = boost::intrusive;
template<class T>
class Tracker : public bi::list_base_hook<bi::link_mode<bi::auto_unlink>>
{
protected:
static bi::list<Tracker, bi::constant_time_size<false>> objects_;
Tracker() noexcept { objects_.push_back(*this); }
Tracker(Tracker const&) noexcept { objects_.push_back(*this); }
public:
static auto count() noexcept { return objects_.size(); }
};
template<class T>
bi::list<Tracker<T>, bi::constant_time_size<false>> Tracker<T>::objects_;
struct Employee : Tracker<Employee> {};
struct Employee2 : Employee {};
int main() {
std::cout << Tracker<Employee>::count() << '\n';
{
Employee e0;
Employee2 e1;
std::cout << Tracker<Employee>::count() << '\n';
}
std::cout << Tracker<Employee>::count() << '\n';
}
Outputs:
0
2
0
Tracker without Boost library:
struct AutoListNode {
AutoListNode *next_ = this, *prev_ = this;
AutoListNode() noexcept = default;
AutoListNode(AutoListNode const&) = delete;
AutoListNode& operator=(AutoListNode const&) = delete;
~AutoListNode() noexcept { this->erase(); }
void push_back(AutoListNode* node) noexcept {
auto prev = prev_;
node->prev_ = prev;
node->next_ = this;
prev->next_ = node;
prev_ = node;
}
void erase() noexcept {
auto next = next_;
auto prev = prev_;
prev->next_ = next;
next->prev_ = prev;
}
size_t size() const noexcept {
size_t count = 0;
for(auto node = next_; node != this; node = node->next_)
++count;
return count;
}
};
template<class T>
class Tracker : private AutoListNode
{
protected:
static AutoListNode objects_;
Tracker() noexcept { objects_.push_back(this); }
Tracker(Tracker const&) noexcept { objects_.push_back(this); }
public:
static auto count() noexcept { return objects_.size(); }
};
template<class T>
AutoListNode Tracker<T>::objects_;
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) {}
};
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!