I am working on a class hierarchy where I have a base class containing a value which needs to be shared with all other derived classes in my code. I currently have this working by using a static double within a base class with pure virtual functions to set the value:
class base {
public:
static double shared_value;
virtual void set_value(double v) = 0;
virtual double get_value() = 0;
};
class derived1 : public base {
public:
void set_value(double v){ shared_value = v; }
double get_value() { return shared_value; }
};
class derived2 : public base {
public:
void set_value(double v){ shared_value = v; }
double get_value() { return shared_value; }
};
etc...
The problem comes when I use header files with my code. I know I can't define a static member variable more than once, and using the headers is giving me multiple initialization errors.
I am not sure how else I can set and view this variable from any of the classes, any help will be hugely appreciated.
You will need to define shared_value in a source file like so:
double base::shared_value = 0;
Now any child class can access that value including editing it.
Related
At the moment, I have a parent class and 2 child classes declared in Setplay.h, as such
namespace agent {
class Setplay {
public:
virtual int reset() {return 0;};
};
class ChildSetplay1 : public Setplay {
public:
virtual int reset();
};
class ChildSetplay2 : public Setplay {
public:
virtual int reset();
};
}
And in a Setplay.cpp, I define the methods
namespace agent {
int ChildSetplay1::reset(){
return 1;
}
int ChildSetplay2::reset(){
return 2;
}
}
Is there a way to avoid re-declaring the methods in the .h and still define unique methods for each child?
If I avoid re-declaring the methods in the .h:
namespace agent {
class Setplay {
public:
virtual int reset() {return 0;};
};
class ChildSetplay1 : public Setplay {};
class ChildSetplay2 : public Setplay {};
}
Then I get the following error:
error: no ‘int agent::ChildSetplay1::reset()’ member function declared in class ‘agent::ChildSetplay1’
But I can't define different methods for each child if I change the methods' signature to something like
int reset(){
return ??; // return 1? 2?
}
I'm not sure there is a way to do this, but my motives are:
the actual classes have several methods and re-declaring everything all the time looks ugly
I still need to keep everything inside the .cpp and .h
So, is it possible? Or are there better alternatives?
You need to define the function for every child, so you can't escape this. What you can do, is to go a little bit around and use a #define if you have multiple functions
Like:
#define SET_PLAY_FUNCTIONS public:\
virtual int reset();\
virtual int go();
namespace agent {
class Setplay {
public:
virtual int reset() {return 0;};
virtual int go();
};
class ChildSetplay1 : public Setplay {
SET_PLAY_FUNCTIONS
};
class ChildSetplay2 : public Setplay {
SET_PLAY_FUNCTIONS
};
}
At least you can save something.....
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.
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
class Class1 {
Class1() { Class2::counter++;}
}
class Class2: public Class1 {
public:
static int counter;
}
The above is an example of what I am trying to do. I am trying to use a static variable of a subclass in the superclass but that gives me a compiler error since Class1 is initialized first and when the compiler reaches the Class2::counter++; it has not initialized Class2 yet and therefore I get a "Class2 has not been declared" error. How can I fix this? Do I need to change my logic completely?
From a OOP perspective a parent class is not able to access to a child field or property, it should the opposite way a child accessing to a parent field or property. I'm wondering whyeyou need to access tora child field from the parent? If you provide more details what you are trying to achieve the best solution will be provided by someone.
You could just pass a reference to your counter to the base class:
class Class1 {
public:
Class1(int& counter) { ++counter; }
};
class Class2: public Class1 {
public:
static int counter;
Class2() : Class1(counter) { }
};
int Class2::counter = 0;
You may put definition of constructor Class1 after Class2 definition:
class Class1 {
public:
Class1();
};
class Class2: public Class1 {
public:
static int counter;
};
int Class2::counter = 0;
Class1::Class1() { Class2::counter++;}
Live demo
A rule of thumb: base classes don't access child class members or methods.
If the base class needs something from a child class, declare an abstract virtual function in the base class for the child to implement.
Or move the common data members or methods into the base class.
In your case:
class Base
{
virtual void increment_counter(void) = 0;
void my_method(void)
{
increment_counter();
}
};
class Child : public Base
{
int counter;
void increment_counter(void)
{
++counter;
}
};
Simply define the constructor of class Class1 after the definition of Class2.
class Class1 {
public:
Class1();
}
class Class2: public Class1 {
public:
static int counter;
}
Class1::Class1() { Class2::counter++;}
Do not forget to define the static data member of Class2.:)
If you want to get freaky with templates, this sounds a possible use for the curiously recurring template pattern. For example:
template <typename T>
class CRTBase
{
CRTBase() { T::counter++; }
};
class CRTDerived : public CRTBase<CRTDerived>
{
public:
static int counter;
};
int CRTDerived::counter = 0;
I would to block child classes from overriding a base method and have the child classes override a new method in a parental class. In other words, a child class of the base class blocks the base class methods and delegates to a new method that further child classes must override. I still want the base class method to be available.
Here is an example:
#include <iostream>
#include <string>
struct Base
{
virtual const std::string& class_name(void) = 0;
};
struct Level1
: public Base
{
private: // Prevent child classes from overriding
// the Base::class_name method
const std::string& class_name(void)
{
static std::string name;
name = "class" + class_name_from_level_1();
return name;
}
protected:
// This is the "new" or redirected class that child classes
// must override.
virtual const std::string& class_name_from_level_1(void) = 0;
};
struct Level2
: public Level1
{
static std::string name;
const std::string& class_name_from_level_1(void)
{
if (name.length() == 0)
{
name = "Level2";
}
return name;
}
};
int main(void)
{
Level2 lev2;
std::cout << lev2.class_name() << "\n";
return 0;
}
I am getting the following errors from g++:
$ g++ hiding_virt_methods.cpp -o hiding_virt_methods.exe
hiding_virt_methods.cpp: In function `int main()':
hiding_virt_methods.cpp:15: error: `virtual const std::string& Level1::class_name()' is private
hiding_virt_methods.cpp:43: error: within this context
In the above example, I want the following chain of execution for Level2:
Base::class_name() --> Level1::class_name_from_level_1() --> Level2::class_name_from_level_1()
Also, I only want to block inheritance of specific methods in the Base class. Protected and Private Inheritance affect all the public methods.
So how do I stop the chain of inheritance of specific Base methods at different levels in the inheritance tree?
Edit: Real world example.
I have an interface class Record. Class Record_With_Id inherits from class Record and adds an ID field. The class Record contains an accept_visitor method. Class Record_With_Id overrides accept_visitor to apply to the ID field, then calls a virtual method, record_with_id_accept_visitor, which descendants must implement.
For your immediate problem, you can rename your class_name() functions to class_name_impl() or similar, then in the base class have a class_name() function that calls the implementation one. That way, only the base class version will match when calling class_name() on a derived object.
More generally, you can frustrate attempts to call the base class methods by having same-named functions in the derived classes - as you've done, but anyone can cast to a Base& and call whatever they like. You can't stop virtual methods being overridable in derived classes... you can only frustrate their use.
It's worth remembering that a publicly derived class IS an instance of the base class, and SHOULD provide the base class's interface.
EDIT: re yout "real world example" edit, can you explain the problem with a normal implementation ala...
#include <iostream>
struct Visitor
{
virtual void operator()(int&) const = 0;
};
struct X
{
virtual void visit(Visitor& v) { v(a); v(b); }
int a;
int b;
};
struct X_with_C : X
{
int c;
virtual void visit(Visitor& v) { X::visit(v); v(c); }
};
struct My_Visitor : Visitor
{
void operator()(int& n) const { std::cout << ++n << '\n'; }
};
int main()
{
X x;
x.a = 10;
x.b = 20;
My_Visitor visitor;
x.visit(visitor);
X_with_C xc;
xc.a = -10;
xc.b = -20;
xc.c = -30;
xc.visit(visitor);
X& rx = xc;
rx.visit(visitor);
}
Output:
11
21
-9
-19
-29
-8
-18
-28
hasn't C++11 added final and override?
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final
Four years later, let me add that C++11 has introduced keyword final:
class Base final {
This can also be applied on the virtual methods:
class Base{
protected:
virtual void doWork() = 0;
public:
virtual void startWork() final { doWork(); }
};
class Derived: public Base{
protected:
virtual void doWork() override { /* some work */ }
public:
// error: overriding final function ‘virtual void Base::startWork()’
virtual void startWork() override { /* something else */ }
};
Visual Studio 2005 and above implement a keyword "sealed", which is a Microsoft extension to C++. You put it in the declaration of Level1::class_name(). I don't think there is a portable way.
It appears that you're trying to do something in a way that's hard.
Depending on what it is that you're trying to achieve, the following may be a solution.
#include <iostream>
#include <string>
struct Base
{
virtual std::string class_name() const = 0;
};
class Level1
: public Base
{
public:
std::string class_description() const
{
return "class " + class_name();
}
};
class Level2
: public Level1
{
public:
virtual std::string class_name() const
{
return "Level2";
}
};
int main()
{
Level2 lev2;
std::cout << lev2.class_description() << "\n";
}
In the above code I've assumed it's for debugging/tracing or something like that. For id purposes look into typeid (a built-in operator).
Cheers & hth.,