Changing base class value in c++ - c++

I'm facing a problem with a few inherited classes and their base class as well.
For example:
base class{
int x,y; // Doesnt really matter
int counter;
public:
class(int x, int y):x(x), y(y), counter(1){}
void add_counter(){counter++;}
//stuff
virtual ~base(){}
}
class1:public base{
public:
class1():base(1,2){}
}
Every of my inherited classes (which I've a few) they all pass the x,y differently from each other. And then I want this counter to increment when I call it.
The problem I'm facing is that the counter increases ONLY on that iteration. No object is being re-constructed (because I debugged). If I call the add_counter for the class1 it will increase from 1 to 2 but if I call it again it will be the same (1 to 2).
What am I missing here?
Thank you.

What am I missing here?
It seems to me that you want to keep track of the number of objects constructed whose types are derived from Base.
In that case, you need to make counter a static member variable, which will require you to make add_counter a static member function.
However, that will require you to:
Decrement the count in the destructor.
Add a copy constructor in Base to make sure that objects created using a copy constructor are also counted.
Here's a simplified version of base to do that:
class base
{
public:
base() { inrement_counter(); }
base(base const& copy) { inrement_counter(); }
virtual ~base(){ decrement_counter(); }
private:
static int counter;
static void inrement_counter() {++counter;}
static void decrement_counter() {--counter;}
}
int base::counter = 0;
If you want to keep track of the number of derived1 objects constructed, you'll need to add the bookkeeping code to derived1. You can create a class template to streamline that process.
Example:
template <typename T>
struct ObjectCounter
{
ObjectCounter() { inrement_counter(); }
ObjectCounter(ObjectCounter const& copy) { inrement_counter(); }
virtual ~ObjectCounter(){ decrement_counter(); }
static int counter;
static void inrement_counter(){++counter;}
static void decrement_counter(){--counter;}
};
template <typename T>
int ObjectCounter<T>::counter = 0;
class base
{
};
class derived1 : public base, public ObjectCounter<derived1>
{
};
class derived2 : public base, public ObjectCounter<derived2>
{
};
#include <iostream>
int main()
{
derived1 d1;
derived2 d2;
auto d3 = d2;
std::cout << d1.counter << std::endl;
std::cout << d2.counter << std::endl;
}
Output:
1
2

Related

Behavior of static variables in objects of derived classes [duplicate]

If I have something like
class Base {
static int staticVar;
}
class DerivedA : public Base {}
class DerivedB : public Base {}
Will both DerivedA and DerivedB share the same staticVar or will they each get their own?
If I wanted them to each have their own, what would you recommend I do?
They will each share the same instance of staticVar.
In order for each derived class to get their own static variable, you'll need to declare another static variable with a different name.
You could then use a virtual pair of functions in your base class to get and set the value of the variable, and override that pair in each of your derived classes to get and set the "local" static variable for that class. Alternatively you could use a single function that returns a reference:
class Base {
static int staticVarInst;
public:
virtual int &staticVar() { return staticVarInst; }
}
class Derived: public Base {
static int derivedStaticVarInst;
public:
virtual int &staticVar() { return derivedStaticVarInst; }
}
You would then use this as:
staticVar() = 5;
cout << staticVar();
To ensure that each class has its own static variable, you should use the "Curiously recurring template pattern" (CRTP).
template <typename T>
class Base
{
static int staticVar;
};
template <typename T> int Base<T>::staticVar(0);
class DerivedA : public Base<DerivedA> {};
class DerivedB : public Base<DerivedB> {};
They will share the same instance.
You'll need to declare separate static variables for each subclass, or you could consider a simple static map in which you could store variables that are referenced by derived classes.
Edit: A possible solution to this would be to define your base class as a template. Having a static variable defined in this template would mean that each derived class will have it's own instance of the static.
There is only one staticVar in your case: Base::staticVar
When you declare a static variable in a class, the variable is declared for that class alone. In your case, DerivedA can't even see staticVar (since it's private, not protected or public), so it doesn't even know there is a staticVar variable in existence.
The sample code given by #einpoklum is not working as it is because of the missing initialization of the static member foo_, missing inheritance in FooHolder declaration, and missing public keywords since we are dealing with classes. Here is the fixed version of it.
#include <iostream>
#include <string>
class A {
public:
virtual const int& Foo() const = 0;
};
template <typename T>
class FooHolder : public virtual A {
public:
const int& Foo() const override { return foo_; }
static int foo_;
};
class B : public virtual A, public FooHolder<B> { };
class C : public virtual A, public FooHolder<C> { };
template<>
int FooHolder<B>::foo_(0);
template<>
int FooHolder<C>::foo_(0);
int main()
{
B b;
C c;
std::cout << b.Foo() << std::endl;
std::cout << c.Foo() << std::endl;
}
I know that this question has already been answered but I would like to provide a small example of inheritance with static members. This is a very nice way to demonstrate the usefulness as well as what is happening with the static variables and the respective constructors.
FooBase.h
#ifndef FOO_BASE_H
#define FOO_BASE_H
#include <string>
class FooBase {
protected:
std::string _nameAndId;
private:
std::string _id;
static int _baseCounter;
public:
std::string idOfBase();
virtual std::string idOf() const = 0;
protected:
FooBase();
};
#endif // !FOO_BASE_H
FooBase.cpp
#include "FooBase.h"
#include <iostream>
int FooBase::_baseCounter = 0;
FooBase::FooBase() {
_id = std::string( __FUNCTION__ ) + std::to_string( ++_baseCounter );
std::cout << _id << std::endl;
}
std::string FooBase::idOfBase() {
return _id;
}
std::string FooBase::idOf() const {
return "";
} // empty
DerivedFoos.h
#ifndef DERIVED_FOOS_H
#define DERIVED_FOOS_H
#include "FooBase.h"
class DerivedA : public FooBase {
private:
static int _derivedCounter;
public:
DerivedA();
std::string idOf() const override;
};
class DerivedB : public FooBase {
private:
static int _derivedCounter;
public:
DerivedB();
std::string idOf() const override;
};
#endif // !DERIVED_FOOS_H
DerivedFoos.cpp
#include "DerivedFoos.h"
#include <iostream>
int DerivedA::_derivedCounter = 0;
int DerivedB::_derivedCounter = 0;
DerivedA::DerivedA() : FooBase() {
_nameAndId = std::string( __FUNCTION__ ) + std::to_string( ++DerivedA::_derivedCounter );
std::cout << _nameAndId << std::endl;
}
std::string DerivedA::idOf() const {
return _nameAndId;
}
DerivedB::DerivedB() : FooBase() {
_nameAndId = std::string( __FUNCTION__ ) + std::to_string( ++DerivedB::_derivedCounter );
std::cout << _nameAndId << std::endl;
}
std::string DerivedB::idOf() const {
return _nameAndId;
}
main.cpp
#include "DerivedFoos.h"
int main() {
DerivedA a1;
DerivedA a2;
DerivedB b1;
DerivedB b2;
system( "PAUSE" );
return 0;
}
If __FUNCTION__ is not working for you in your constructors then you can use something similar that can replace it such as __PRETTY_FUNCTION__ or __func__, or manually type out each class's name :(.
Alas, C++ has no virtual static data members. There are several ways to simulate this, more or less:
#GregHewgill's solution has you replicate the static variable in each derived class; this solution is simple, straightforward and doesn't introduce additional classes, but I don't like this one since it's verbose, and you have to be rather disciplined with it.
#MarkIngram suggested a CRTP-based solution, which saves you most of the typing; however, it messes up the inheritance structure, because what were previously subclasses of A are no longer really related as classes. After all, two templated types with the same name but different template arguments could be just any two types.
I suggest a different CRTP-based solution, using a mix-in class:
class A {
virtual const int& Foo() const = 0;
}
template <typename T>
class FooHolder {
static int foo_;
const int& Foo() const override { return foo_; }
}
class B : A, virtual FooHolder<B> { }
class C : B, virtual FooHolder<B> { }
The only thing you need to do in a subclass is also indicate the mix-in inheritance. There might be some virtual inheritance caveats I'm missing here (as I rarely use it).
Note that you either have to instantiate and initialize each subclass' static variable somewhere, or you can make it an inline variable (C++17) and initialize it within the template.
This answer was adapted from my answer to a dupe question.

C++ static member modifiers for subclasses

Consider the following code:
#include <stdio.h>
#include <iostream>
/// Header-file
class Base {
public:
virtual void do_something() const =0;
int GetAttrib () const {return constattribute_;};
static const int constattribute_;
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
};
class DerivedB : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
};
/// CC-file
using namespace std;
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
The intend being that i have some abstract interface (Base) which defines also a variable, which should be present for all derived classes, and is retrievable. All flavours of subclasses should be forced to/able to redefine their specific value for this variable, at best during class declaration (the values are known at the time the class is declared after all).
I want to achieve code, not altering the main()-program so that the output is '12' and not as of now (uncommenting current lines in the code) '00' (Doing so shadows the fields from base class).
I tried to look into the matter, and there are different paths for solutions, many of which however go contrary to my intuition:
1. Some follow the CRTP pattern, which is however impossible if I want to address my subclasses by their base-ptr in main.
2. Other solutions require to virtualize the 'GetAttrib()' function for every derived instance., which is cumbersome, and action of modifying the attribute is masked within a function definition.
3. A third possibility is to remove the static pattern and have the 'constattribute_' field as a regular member, which however forces me to drag it through all constructors as a parameter.
I am quite sure that there must be some smarter way to do this. Any hints are appreciated.
Using CRTP may get you what you want, assuming you don't have to access GetAttr() through Base* and can leave without constattribute_ in Base itself. Just follow the rule that every programming problem can be solved by entering another level of indirection, which I did below:
class Base {
public:
virtual void do_something() const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
If you need GettAttr from top to bottom of the inheritance tree you can modify the above code a bit, but this will cost you making GetAttr virtual (but still one implementation only):
class Base {
public:
virtual void do_something() const = 0;
virtual int GetAttrib () const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
Please note that I don't know how well (or bad) it will behave with deep inheritance tree (ie. when inheriting from DerivedA and/or DerivedB). In this case I would probably remove BaseConstAttr from inheritance tree right below Base and would try to inject it between most derived class and its predecessor or use multiple inheritance.
What you are requesting requires virtual dispatch somewhere, because you don't know the type of the object you are dealing with until runtime. The purpose of virtual dispatch is to solve exactly the problem you are facing.
The simplest solution is what you have given as number 2: make GetAttrib() virtual, and implement it on each derived class where you introduce a shadowing constattribute_.
static variable in base class is single instance hence it will be reflected same in derived class.
You can make same static member variable in derived class with specific different value you want. Now make getter member function of static variable in Base class as virtual and overload it in derived class which returns is static instance value.
I have update your code to work it, please check ..
#include <iostream>
using namespace std;
class Base {
public:
static const int constattribute_;
virtual void do_something() const =0;
virtual int GetAttrib () const {return constattribute_;};
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
class DerivedB : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
You should get desired output.
Note : Remember all member variables and func in derived class are private.

Can I declare a different typedef depending on class?

Is it possible to have a different type definition based on which derived class is instantiated?
Say I have a parent class with a virtual function func(), two int members and a vector of type myType, and two child classes, which share the same int members, and the vector, but their implementation of func() require myType to be slightly different.
For example:
class Parent {
protected:
int myMember;
int myOtherMember;
std::vector<myType> vec;
public:
Parent(variable);
virtual int func() = 0;
}
class Child1 : public Parent {
private:
typedef <some type definiton> myType;
public:
Child1(variable) : Parent(variable){};
int func() {return someFunc();};
}
class Child2 : public Parent {
private:
typedef <some other type definiton> myType;
public:
Child2(variable) : Parent(variable){};
int func() {return someOtherFunc();};
}
Can I do something like this? when I have tried it, it creates a circular dependency in the header files, because class Parent is required to be included first, but then it requires myType to be defined.
Is there a way of forward declaring myType depending on class? or do I just need to include a different vector of myType in each class like so:
class Parent {
protected:
int myMember;
int myOtherMember;
public:
Parent(variable);
virtual int func() = 0;
}
class Child1 : public Parent {
private:
typedef <some type definiton> myType;
std::vector<myType> vec;
public:
Child1(variable) : Parent(variable){};
int func() {return someFunc();};
}
class Child2 : public Parent {
private:
typedef <some other type definiton> myType;
std::vector<myType> vec;
public:
Child2(variable) : Parent(variable){};
int func() {return someOtherFunc();};
}
This is a job for templateman!
First we declare Parent
template <class TYPE>
class Parent {
protected:
int myMember;
int myOtherMember;
std::vector<TYPE> vec;
public:
Parent(TYPE variable);
virtual int func() = 0;
};
Unfortunately a custom type contained within Child1 is out with this approach because the type needs to be declared before we can specialize a template on it. I'm using int and double here for ease. Replace as needed.
using Child1Type = int;
// or typedef int Child1Type; pre-C++11
class Child1 : public Parent<Child1Type> {
public:
Child1(Child1Type variable) : Parent(variable){};
int func() {return someFunc();};
};
using Child2Type = double;
class Child2 : public Parent<Child2Type> {
public:
Child2(Child2Type variable) : Parent(variable){};
int func() {return someOtherFunc();};
};
EDIT
Kicking myself for not getting this earlier (and burning way too much time because I knew it had to be possible, but was thinking in the wrong direction)
Declare the type up in Parent. Set the access based on who need to be able to see the type. Here I made Type public to test it out in main. The Type is declared in Parent and is visible to (and through because it's public) the Children.
Also stripped out everything that wasn't immediately necessary and used fixed width integer types so I could easily demonstrate the differences.
I think this is exactly what Pixelchemist was alluding to.
template <class TYPE>
class Parent {
public:
using Type = TYPE; // declare Type here
protected:
int myMember;
int myOtherMember;
std::vector<Type> vec; // visible here
public:
Parent(Type variable); // here
virtual ~Parent(){}
virtual int func() = 0;
};
class Child1 : public Parent<uint16_t> { // complicated type needs to be reproduced
// only once, here in the specialization
public:
Child1(Type variable) : Parent(variable){};
};
class Child2 : public Parent<uint32_t> {
public:
Child2(Type variable) : Parent(variable){};
};
int main()
{
// and visible way down here in main through Child1 and Child2
std::cout << "Child 1: " << sizeof(Child1::Type) << std::endl;
std::cout << "Child 2: " << sizeof(Child2::Type) << std::endl;
}
output is
Child 1: 2
Child 2: 4
You could simply use templates:
template<class T>
struct Base
{
std::vector<T> v;
};
struct D1 : public Base<int>
{
// all stuff in here comes into play when deriving from Base is already done
// Thus, compiler cannot know any typedefs from here inside Base...
};
struct D2 : public Base<double>
{
};
where you cannot use a typedef from derived in base class. See CRTP refer to typedef in derived class from base class.
This is what templates are for:
<template typename T>
class Child : public Parent {
private:
std::vector<T> vec;
public:
Child(variable) : Parent(variable) {};
int func() { return someOtherFunc(); };
}
Then Child is declared as something like:
Child<int> myChildInstance(10);

C++ What is the expected behavior of passing a 'this' pointer to a base class and then store it in as another base class of the child class

So i have a vector<Base> and Base is the base class of multiple children, some of his children may be templated classes. I want to access the child classes from this base class without using dynamic_casting I cant also change the base class to an abstract class. Here is what I did
struct Ainterface {
virtual double GetVal() = 0;
};
struct Binterface {
virtual bool Getbo() = 0;
virtual int Getty() = 0;
};
struct Base {
Base(int id, Ainterface* inter):
id_(id),
a_interface_(inter){}
Base(int id, Binterface* inter):
id_(id),
b_interface_(inter){}
int id_;
Ainterface* a_interface_;
Binterface* b_interface_;
};
struct A : Base, Ainterface {
A():
Base(1, this),
val(5.5){}
double val;
double GetVal(){return val;}
};
template<typename T>
struct B : Base, Binterface {
B():
Base(2, this),
ty(5){}
int ty;
bool Getbo(){ return t_class.get();}
int Getty(){ return ty;}
T t_class;
};
...
...
int main(){
std::vector<Base> base;
base.push_back(A());
auto some = base.back();
switch (some.id_) {
case 1:
std::cout << some.a_interface_->GetVal() << std::endl;
break;
case 2:
std::cout << some.b_interface_->Getbo() << some.b_interface_->Getty() << std::endl;
default:
break;
}
return 0;
}
OUTPUT
5.5
Is this a safe thing to do?
Is there a better way to achieve this?
Thanks
When you declare a variable of type vector<Base>, the vector only allocates space for values of class Base, not any of the derived classes. When you push back a temporary A it is actually sliced and becomes a Base. The GetVal method only works by accident as the memory in which the temporary resided hasn't been reclaimed yet.
So, no, this is not a safe thing to do. It is undefined behaviour.
If you want to have a vector of objects that can vary in type, you have to use some kind of pointer. Ideally, you would use a vector<shared_ptr<Base>>.

What is the best way to handle a collection of derived objects in a derived class

Imagine I have a class 'BaseA' that contains a collection of items 'ItemA'.
Now I want to extend 'BaseA' to add extra capabilities, so I derive 'DerivedA' from 'BaseA'.
One characteristic of 'DerivedA' is that it has to handle more sophisticated 'DerivedITemA' items instead of 'ItemA' ones.
class BaseA {
protected:
vector<ItemA> x;
void m1(int i) { x.m1(i); }
};
class ItemA {
protected:
void m1(int i) { ... }
};
class DerivedItemA : public ItemA {
void m2(int i) { ... }
};
Now I would like to handle something of this sort:
class DerivedA : public BaseA {
vector<DerivedItemA> x;
void m2(int i) { x[i].m2(); }
};
I.e. have my Derived class handle derived items. The above definition of x is incorrect as it clashes with the one in BaseA. But the idea is I want to be able to reuse all methods in BaseA that handle x as long as they deal with ItemA elements and have the extended methods in DerivedA to handle the extra intricacies of DerivedItemA type of data
Any suggestion? My current thoughts are in the lines of defining a new datatype for x (VectorOfItemA for instance) and derive from it VectorOfDerivedItemA. I wonder if there is a simpler / better solution.
Thanks
I believe you need to have pointers in your vectors in order to handle this. I'm a little confused what value to pass to m1 and m2 since i appears to be an index, but here's my guess:
class BaseA {
protected:
vector<ItemA*> x;
void m1(int i) { x[i]->m1(i); }
};
class ItemA {
protected:
void m1(int i) { ... }
};
class DerivedItemA : public ItemA {
void m2(int i) { ... }
};
class DerivedA : public BaseA {
vector<DerivedItemA*> y; //don't shadow the base class vector!
void m2(int i) { y[i]->m2(i); }
};
Then, when you add an item in DerivedA, add it to both x and y. That way BaseA can do it's thing to the pointer in x and DerivedA can do its thing on the pointer in y.
Edit: you'll also need to provide a virtual method for adding items otherwise you might get things added to BaseA.x that don't get added to DerivedA.y.
Do you own all the classes? If so, you can refactor into a template base class instead.
template <typename ITEM>
class BaseT {
protected:
vector<ITEM> x;
void m1(int i) { x[i].m1(); }
};
typedef BaseT<ItemA> BaseA;
class DerivedA: public BaseT<DerivedItemA> {
void m2(int i) { x[i].m2(); }
};
If you intend to re-use code that takes BaseA to also accept a DerivedA, then you may need to modify them to be template functions/classes as well.
Otherwise, you will need some kind of "polymorphic" base object for the vector. You can look at Retrieve data from heterogeneous std::list (or my follow up question: unique_ptr member, private copy constructor versus move constructor) for one such approach.
As an alternative to a polymorphic item, you can define an interface for your base.
class BaseI {
protected:
virtual void m1(int) = 0;
//... other interfaces
public:
virtual ~BaseI () {}
//... other public interfaces
};
template <typename ITEM>
class BaseT : public BaseI {
protected:
vector<ITEM> x;
void m1(int i) { x[i].m1(); }
//...implement the other interfaces
};
//...
Now, code that takes a BaseA needs to be refactored to take a BaseI instead. That new code will be able to accept a DerivedA as well.
You may try to use Curiously Recurring Template Pattern - CRTP:
live demo
#include <iostream>
#include <ostream>
#include <vector>
using namespace std;
struct Item
{
void m1(int i)
{
cout << "m1(" << i << ")" << endl;
}
};
struct DerivedItem : Item
{
void m2(int i)
{
cout << "m2(" << i << ")" << endl;
}
};
template<typename Derived>
struct IBase
{
void m1(int i)
{
for(auto &&z : static_cast<Derived*>(this)->x)
{
z.m1(i);
}
}
};
template<typename Derived>
struct IDerivedBase: IBase<Derived>
{
void m2(int i)
{
for(auto &&z : static_cast<Derived*>(this)->x)
{
z.m2(i);
}
}
};
struct Base : IBase<Base>
{
vector<Item> x;
};
struct DerivedBase : IDerivedBase<DerivedBase>
{
vector<DerivedItem> x;
};
int main()
{
Base b;
b.x.resize(3);
DerivedBase d;
d.x.resize(1);
b.m1(11);
d.m1(22);
d.m2(33);
}
Output is:
m1(11)
m1(11)
m1(11)
m1(22)
m2(33)
Vector will contain either all elements as ItamA in BaseA instantiations or all elements of DerivedItemA in DerivedA instantiaions. There is no need to mix.
There is no any mix at this approach:
Base has only vector<Item> providing m1 method
DerivedBase has only vector<DerivedItem> providing m1 and m2 methods.
However, without knowing real usage pattern - it is hard to guess what you need. Maybe for your case two standalone vectors would be enough:
vector<Item> x1;
vector<DerivedItem> x2;
and just define stand-alone functions for them.