Best way to essentially make an overridden constant variable? - c++

I want to make something functionally similar to this:
class Base
{
public:
const int ClassID = 1;
}
class Derived1 : public Base
{
public:
const int ClassID = 2;
}
class Derived2 : public Base
{
public:
const int ClassID = 3;
}
But, obviously, you can't override variables. What would be the best way to achieve the same functionality?
(The context for this is a video game where there are different troops, overridden from the same parent "BaseTroop" class. I want each troop to have its own ID that can be retrieved from anywhere)
Thanks in advance!

There is no way to change the default member initialiser in derived classes.
But, there is no need to rely on the default initialiser. You can provide an initialiser in the constructor:
struct Derived1 : Base
{
Derived1(): Base{2} {}
};
struct Derived2 : Base
{
Derived2(): Base{3} {}
};

Add a virtual function, returning the ID. You can also have a static variable or function returning the same ID, in case you want to get it without a class instance. You can also assign the IDs automatically, using CRTP:
#include <iostream>
struct BaseLow
{
virtual int GetId() const = 0;
virtual ~BaseLow() {}
};
namespace impl
{
int &GetIdCounter()
{
static int ret = 0;
return ret;
}
}
template <typename Derived>
struct Base : BaseLow
{
inline static const int id = impl::GetIdCounter()++;
int GetId() const override final
{
return id;
}
};
struct Derived1 : Base<Derived1> {};
struct Derived2 : Base<Derived2> {};
int main()
{
std::cout << Derived1::id << '\n'; // 0
std::cout << Derived2::id << '\n'; // 1
Derived1 d1;
Derived2 d2;
BaseLow *ptrs[] = {&d1, &d2};
for (BaseLow *ptr : ptrs)
std::cout << ptr->GetId() << '\n'; // 0, 1
}

Related

How to say to the derived class which protected base class member to use

Consider the example below:
class Base {
protected:
struct SubStruct { double value; };
};
class Derived : public Base {
public:
Derived() {
data.value = 3.14;
}
Base::SubStruct data;
};
int main()
{
Derived instance;
std::cout << instance.data.value << std::endl;
return 0;
}
The Derived class has the data member of the type that is defined in its base class. Pay special attention to that the SubStruct type is protected in Base.
Now I'm enhancing the Base with a choice of substructs. To select which substruct to use I'm making the Derived template:
class Base {
protected:
struct SubStructInt { int value; };
struct SubStructDouble { double value; };
};
template<typename S>
struct Derived : public Base {
Derived() {
data.value = 3.14;
}
S data;
};
int main()
{
Derived<Base::SubStructInt> instanceInt;
std::cout << instanceInt.data.value << std::endl;
Derived<Base::SubStructDouble> instanceDouble;
std::cout << instanceDouble.data.value << std::endl;
return 0;
}
That doesn't compile because the substructs are protected, and I cannot instantiate the Derived with the types protected in Base (everything works if I make them public).
I don't want to make the substructs public, so I found a solution with std::conditional:
template<bool flag>
struct Derived : public Base {
using SubStruct = std::conditional_t<flag, SubStructInt, SubStructDouble>;
Derived() {
data.value = 3.14;
}
SubStruct data;
};
Anyway, I think that this is not the best/idiomatic solution to the problem: "how to say to the derived class which protected type of the base class to use". At the end of the day the protected subtypes are visible within Derived, and can be aliased from there:
template<typename S>
struct Derived : public Base {
using DerivedInt = Derived<SubStructInt>;
using DerivedDouble = Derived<SubStructDouble>;
// ...
};
Is there a better way?

How to share same data between multiple instances at inheritance levels?

I'd like to instance multiple object of the same inheritance levels, and for each of these level use the same data. So I think about inheritance and static members of a class.
This is my attempt:
#include <iostream>
class Father
{
public:
static int sValue;
inline int GetValue() { return sValue * 10; }
};
class Child1 : public Father
{
public:
};
class Child2 : public Father
{
public:
};
int Father::sValue = 0;
int main()
{
Child1 child1_1;
Child1 child1_2;
Child2 child2_1;
Child2 child2_2;
child1_1.sValue = 1;
child2_1.sValue = 2;
std::cout << child1_2.GetValue() << std::endl;
std::cout << child2_2.GetValue() << std::endl;
}
In my example both Child1 instances should return 10 with GetValue(), and both Child2 instances should return 20 using GetValue(). Since the function its the same, I don't want to override it for each child (that's why I placed it in Father).
The problem is that also Child1 instances returns 20 calling GetValue().
Thus static is shared across "main" parent, not child.
Since that sValue value is used into GetValue(), its correct to place it here. But I cannot separate static/same data so.
How would you do this?
splrs user has correctly identified your problem and the solution is correct. You need two different functions with two different static objects. You can avoid repeating the code, by using a template:
template<class Child>
struct Father {
static int sValue;
int GetValue() { /* ... */ }
};
struct Child1 : Father<Child1> {};
struct Child2 : Father<Child2> {};
This idiom is known as Curiously recurring template pattern.
Now of course, there is no common parent. If you need that, you can inherit the template from a non-template base:
struct FatherBase {};
template<class Child>
struct Father : FatherBase { /*...*/ };
And, if you need to access the different versions of GetValue from the base, then you need a virtual function:
struct FatherBase {
virtual int GetValue() = 0;
};
template<class Child>
struct Father : FatherBase {
// ...
int GetValue() override { /* ... */ }
};
You're modifying Father::sValue when you call child1_1.sValue = 1; and child2_1.sValue = 2; There's one instance, which belongs to Father, so however you access it (via a method against the classes or the instances) you'll get whatever it was set to prior to the call to GetValue().
If you want a Child1 and a Child2 version then add static members and methods to those classes.
I think the following can be what you're after:
class Father
{
public:
inline int GetValue() { return DoGetValue() * 10; }
void SetValue( int value ) { DoSetValue( value ); }
protected:
virtual int DoGetValue() = 0;
virtual void DoSetValue( int value ) = 0;
};
class Child1 : public Father
{
public:
static int sValue;
protected:
int DoGetValue() override { return sValue; }
void DoSetValue( int value ) override { sValue = value; }
};
class Child2 : public Father
{
public:
static int sValue;
protected:
int DoGetValue() override { return sValue; }
void DoSetValue( int value ) override { sValue = value; }
};
int Child1::sValue = 0;
int Child2::sValue = 0;
int main()
{
Child1 child1_1;
Child1 child1_2;
Child2 child2_1;
Child2 child2_2;
child1_1.SetValue( 1 );
child2_1.SetValue( 2 );
std::cout << child1_2.GetValue() << std::endl;
std::cout << child2_2.GetValue() << std::endl;
}

Constant member in inherited class c++

Big edit:
I have a code in which I have to add a constant member in a inherited class by using _elemente (which is a vector). Not to add a member in the inherited classes, just by using _elemente. In every inherited classes (let's say B, C, D and E) I withh have MAX_VAL1, MAX_VAL2 and so on with different values.
I tried:
#include <iostream>
#include <iomanip>
#include <vector>
typedef unsigned int Uint;
typedef vector<Uint> TVint;
typedef vector<Uint>::const_iterator TIterator;
class A
{
protected:
Uint _count;
TVint _elemente;
public:
//
};
class B : public A
{
const int MAX_VAL;
};
But it has a member and I don't have to have a member in the inherited class.
All the code here:
.h: http://pastebin.com/P3TZhWaV
.cpp: http://pastebin.com/ydwy2L5a
The work from the inherited classes is done using that constant members.
if MAX_VAL1 < count
{
throw Exception() {}
}
if (_elemente.size() == 0) // As _elemente is a vector from STL
{
_elemente.push_back(0);
}
for (int i = _elemente.size(); i < count; i++)
{
_elemente.push_back(_elemente[i * (i+1) / 2]);
}
}
I don't think that is correct as I have to use the Vector from STL and I don't really think that is the way the constant member from a inherited class without the actual member declared should be added.
Thanks for your help.
You could use a virtual function, something like this:
class A
{
virtual int max_val() const = 0;
protected:
Uint _count;
TVint _elemente;
public:
//
};
class B : public A
{
int max_val() const { return 42; }
};
if ( max_val() < _count ) ...
Based on other comments it seems like you want a const number that is accessible in the base class which can have a different value depending on the derived class. You could achieve that like this: https://ideone.com/JC7z1P
output:
A: 50
B: 80
#include <iostream>
using namespace std;
class Base
{
private:
const int aNumber;
public:
// CTOR
Base( const int _aNumber ) :
aNumber( _aNumber ) {}
// check value
int getNumber() const
{
return aNumber;
}
};
class A : public Base
{
public:
A() : Base( 50 ) {}
};
class B : public Base
{
public:
B() : Base( 80 ) {}
};
int main() {
A a;
B b;
std::cout << "A: " << a.getNumber() << std::endl;
std::cout << "B: " << b.getNumber() << std::endl;
return 0;
}
When you write like
class B : public A
{
const int MAX_VAL;
};
what value do you expect B's class instance to hold with current approach?
Have you tried to add ctor to B (to initialize MAX_VAL to some exact value), so that whole class definition should be like
class B : public A
{
const int MAX_VAL;
public:
B(int max_val):MAX_VAL(max_val) {}
};
Also, the code above shows a lot of unanswered questions. Some of them:
Do you really need it to be member? mark it as 'static' (static const int MAX_VAL = 5) . That would mean, every B's instance MAX_VAL would be equal
All of type redifinitions don't look meaningful. What if you use intrisic types and auto?
Usually one doesn't compare size() with 0 - just calls empty().
Have you tried to read Stroustrup or Lippman?
If you want to access it statically, you can do it by using templates :
ABase gives polymorphic access to value
A gives static access to value
B and Care examples of usage
.
// This is the polymorphic root class
class ABase
{
public:
ABase(int maxV) : _maxV(maxV) {}
int maxValue() { return _maxV; }
private:
int _maxV;
};
// This class gives static method
template<int V_MaxValue>
class A : public ABase
{
public:
A() : ABase(V_MaxValue) {}
static int maxValue() { return V_MaxValue; }
};
class B : public A<42>
{
};
class C : public A<35>
{
};
// Static access (neex explicit class call) :
// B::maxValue() => 42
// C::maxValue() => 35
//
// Polymorphic call :
// ABase* poly = new B();
// poly->maxValue() => 42

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.

c++ design question: Can i query the base classes to find the number of derived classes satisfying a condition

I have a piece of code like this
class Base
{
public:
Base(bool _active)
{
active = _active;
}
void Configure();
void Set Active(bool _active);
private:
bool active;
};
class Derived1 : public Base
{
public:
Derived1(bool active):Base(active){}
};
similarly Derived 2 and Derived 3
Now if i call derived1Object.Configure, i need to check how many of the derived1Obj, derived2Obj,derived3Obj is active. Should i add this in the "Base" class like a function say, GetNumberOfActive()?
And If the implementation is like this:
class Imp
{
public:
void Configure()
{
//Code instantiating a particular Derived1/2/3 Object
int GetNumberOfActiveDerivedObj();
baseRef.Configure(int numberOfActiveDerivedClasses);
}
prive:
Derived1 dObj1(true);
Derived2 dObj2(false);
Derived3 dObj3(true);
};
should i calculate the numberOfActive Derived Objects in Imp Class?
THanks
One simple possibility:
NumberOfActive should be static in Base. It should get incremented every time the object gets created and active is true.
You could use CRTP in conjunction with a static counter variable: Wikipedia Link
edit: some code
#include <iostream>
template <typename T> struct counter {
counter() { ++objects_alive; }
virtual ~counter() { --objects_alive; }
static int objects_alive;
};
template <typename T> int counter<T>::objects_alive( 0 );
class Base {
public:
void Configure();
//more stuff
};
class Derived1 : public Base, counter<Derived1> {
public:
void Configure() {
std::cout << "num Derived1 objects: "<< counter<Derived1>::objects_alive << std::endl;
}
};
class Derived2 : public Base, counter<Derived2> {
public:
void Configure() {
std::cout << "num Derived2 objects: " << counter<Derived2>::objects_alive << std::endl;
}
};
int main (int argc, char* argv[]) {
Derived1 d10;
d10.Configure();
{
Derived1 d11;
d11.Configure();
Derived2 d20;
d20.Configure();
}
Derived1 d12;
d12.Configure();
Derived2 d21;
d21.Configure();
return 0;
}
Output:
$ g++-4 -pedantic crtp1.cpp -o crtp1 && ./crtp1
num Derived1 objects: 1
num Derived1 objects: 2
num Derived2 objects: 1
num Derived1 objects: 2
num Derived2 objects: 1
in Configure() method you may access to a factory of Derived* objects and get the count of active obcects