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;
Related
I have a templated SafeSingleton class, Base class which is derived from SafeSingleton and implements some base methods. I want to have class that is derived from Base and can be accessed via instance() method of SafeSingleton. The problem is that when I am trying to access Derived::instance() it returns the pointer to a Base class and the compiler doesn't know anything about methods of derived class. What should I do to make below code work.
template<class T>
class SingleTon {
public:
static T* instance()
{
return holder().instance;
}
protected:
template<class I>
struct Holder
{
Holder() : instance(new I())
{
}
I* instance;
};
static Holder<T> &holder()
{
static Holder<T> holder;
return holder;
}
};
// Hopefully issue is here, I am never creating SingleTon<Derived>, but how can it be done?
class Base : public SingleTon<Base> {
public:
Base() = default;
void printBase() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
Derived() = default;
void printDerived() {
std::cout << "Derived";
}
};
int main()
{
Derived::instance()->printBase();
Derived::instance()->printDerived(); // Here is the error
//Error: main.cpp:57:26: error: ‘class Base’ has no member named ‘printDerived’
//57 | Derived::instance()->printDerived();
return 0;
}
template<class D>
class Base : public SingleTon<D> {
and
class Derived : public Base <Derived>
and ... done?
If you want to put Base's non-Ddependent methods in a cpp file, you'll have to get fancy. Have BaseImp that does not derive from SingleTon, put code there. Have Base<D> derive from it and write forwarding glue to it BaseImpl. But you probably don't need this.
I have a class structure that i want to use and i want to use a function of a derived class to be passed as a constructor argument to the base class. I cannot find the right syntax for it (new to C :))
This is the base class that i use and it has a constructor with a callback function:
class SPortSensor {
public:
SPortSensor(sensorData (*pCallback)(SPortSensor*));
sensorData getValue();
private:
sensorData (*getData)(SPortSensor*);
};
This is the derived class that implements the callback function within the class (pCallback) so it has a different constructor and a member function that needs to be passed to the base class constructor:
class SimpleSensor : public SPortSensor {
public:
SimpleSensor(int id);
long value;
private:
int _id;
sensorData pCallback(SPortSensor*);
};
This header compiles fine. The only error i am seeing is in the implementation of the SimpleSensor constructor. I cannot find the right syntax for this:
sensorData SimpleSensor::pCallback(SPortSensor* sensor) {
...
}
SimpleSensor::SimpleSensor(int id) : SPortSensor(pCallback) {
_id = id;
}
Googling this issue didn't help that much since i probably don't use the right search words and don't understand enough of c++ (i am a C# guy).
The circular reference smells like there might be some general ownership issues.
But, one way around your impass is to use std::function<sensorData(SPortSensor*)> instead of the function pointers. Then initialize the base class with a lambda pointing to itself:
SimpleSensor(int id) : SPortSensor([this](SPortSensor* sps) { return pCallback(sps); }) { }
I cannot in good concious condone this, but it didn't explode when I tried it. One caveat is that SimpleSensor won't be initialized when the base constructor is called, so SPortSensor can't call the lambda in its own constructor.
Call-backs usually take place between different objects. One solution is to differ the use of the derived class method after constructor (in an init method for example?), and declare the method as virtual.
#include <iostream>
struct sensorData {
double val = 0;
};
class SPortSensor {
public:
virtual sensorData getValue() {
std::cout << "Base class\n";
sensorData sd;
return sd;
}
};
class SimpleSensor : public SPortSensor {
public:
long value;
SimpleSensor(int id): id(id) {
}
virtual sensorData getValue() {
std::cout << "Derived class\n";
sensorData sd;
return sd;
}
private:
int id;
};
int main() {
SPortSensor base;
SimpleSensor derived(1);
base.getValue();
derived.getValue();
SPortSensor* derivedPtr = new SimpleSensor(2);
derivedPtr->getValue();
return 0;
}
So i think the complexity (issue?) was in trying to do thing with to few lines of code. I simply switched to polymorphy with a abstract class to simplify things.
Abstract base:
class SPortSensor {
public:
void (*valueSend)(void);
virtual sensorData getData () = 0;
};
2 implementation classes:
class CustomSPortSensor : public SPortSensor {
public:
CustomSPortSensor(sensorData (*callback)(CustomSPortSensor*));
private:
sensorData (*_callback)(CustomSPortSensor*);
virtual sensorData getData(){
return _callback(this);
}
};
class SimpleSPortSensor : public SPortSensor {
public:
SimpleSPortSensor(int id);
long value;
private:
int _id;
virtual sensorData getData(){
sensorData data;
data.sensorId = _id;
data.value = value;
return data;
}
};
This now works as expected and is very easy to use and understand (usage of the implementation must as readable as possible).
Now i only want the implementation of the virtual functions to be in the .cpp instead of the .h.......
#include <iostream>
class EquationOfMotion
{
public:
// other attributes
virtual void findNextTimeStep() = 0;
};
class SystemModel
{
public:
EquationOfMotion* p_eom;
// other atributes
SystemModel(EquationOfMotion* new_p_eom)
{
p_eom = new_p_eom;
}
};
class VehicleEquationOfMotion: public EquationOfMotion
{
public:
VehicleEquationOfMotion(...){/* initialise attribute*/}
virtual void findNextTimeStep(){}
};
class Vehicle: public SystemModel
{
// ???? Implementation ?????
}
Vehicle is a specialization of SystemModel where p_eom points to VehicleEquationOfMotion.
I would like to initialise, an instance of VehicleEquationOfMotion and point to it p_eom in Vehicle. I want it to be defined only within the scope of Vehicle, and at the same time, not to use heap.
Is it even possible to reside VehicleEquationOfMotion object inside Vehicle without using the heap? (If not, please suggest where the design has gone wrong).
Might be helpful: I thought about the implementation in this question but ran into trouble (see the question).
If I got your question correctly, then do it like this:
class FooChild : public FooParent
{
public:
FooChild (int pX):m_BarChild(pX), FooParent(&m_BarChild) // point p_barPar to instance of BarChild (i.e. m_BarChild)
{
}
private:
BarChild m_BarChild; // instance of BarChild resided in the stack(not the heap) and is local to FooChild
}
If you want to have FooParent.p_barPar to be pointing to a BarChild that resides inside FooChild, you might need to add a default ctor to FooParent and a method as follows as well: set_p_barPar(BarChild* new_p_bar){p_barPar = new_p_bar;}. So you get:
class FooParent
{
public:
BarParent* p_barPar;
FooParent (){}
FooParent (BarChild* new_p_bar)
{
p_barPar = new_p_bar;
std::cout << p_barPar->x << std::endl;
}
protected:
set_p_barPar(BarChild* new_p_bar)
{
p_barPar = new_p_bar;
}
}
Then you can implement FooChild:
class FooChild : public FooParent
{
public:
FooChild(int new_x, BarChild* new_p_bar):_bar_child(new_x)
{
set_p_barPar(&_bar_child);
}
private: //? Depends on your plans
BarChild _bar_child();
}
Use a class template.
class EquationOfMotion { ... };
template <typename EOM>
class SystemDynamics
{
EOM EquationOfMotion;
...
};
class VehicleEquationOfMotion : public EquationOfMotion { ... };
class Vehicle : public SystemDynamics<VehicleEquationOfMotion> { ... };
May be this is what you want. But the design is not safe. You are passing the pointer to a uninitialized object.
class Vehicle: public SystemModel
{
public:
Vehicle(): SystemModel(&_vem)
{
}
VehicleEquationOfMotion _vem;
}
However, it is safer to do the following:
class SystemModel
{
public:
EquationOfMotion* p_eom;
// other atributes
SystemModel()
{
}
};
class Vehicle: public SystemModel
{
public:
Vehicle(): SystemModel(&_vem)
{
p_eom = &_vem;
}
VehicleEquationOfMotion _vem;
};
Here is my hierarchic of classes.
I have declare following abstract interface class, which have just one function:
class IAuthenticator
{
public:
virtual void CreateJson() = 0;
};
After I have created on more class 'UIData' and inherits it from interface class, in this case:
class UIData : public IAuthenticator
{
protected:
UIData() : mWindowHandle(0)
{ /* Constructor do nothing. **/ }
private:
integer mWindowHandle;
public:
void CreateJson()
{
std::cout<<"UIData::CreateJson\n";
}
};
I have one more class which inherits from UIData
class AuthenticateIn : public UIData
{
private:
string mOrigin;
string mLogoURL;
string mUserID;
public:
void CreateJson()
{
std::cout<<"AuthenticateIn::CreateJson\n";
}
};
Question
In my main function I have write code like this.
int main()
{
AuthenticateIn* ai = new AuthenticateIn();
ai->CreateJson();
}
When I call CreateJson() function I see log "AuthenticateIn::CreateJson". I want to find a way to call CreateJson() and it will be called for all base classes.
I know that I can do that calling this->UIData::CreateJson() from AuthenticateIn class CreateJson function, but is there any other way to do that, some automatic way ? Thanks !!
is there any other way to do that, some automatic way
No, there isn't. You have to call the base class's implementation from the derived class. The compiler won't do this automatically since it doesn't know whether you actually want this.
You have to call the base class function in the derived class sort of like this:
void CreateJson() {
UIData::CreateJSon();
}
etc
No, there is no such way. If you want to call virtual function from base class you should do this directly.
You may not be able to force a call to a virtual base class, but you can use indirection to simulate the behaviour.
typedef int integer;
#include <iostream>
#include <string>
using std::string;
using std::cout;
class IAuthenticator
{
public:
virtual void CreateJson() = 0;
};
class UIData : public IAuthenticator
{
protected:
UIData() : mWindowHandle(0)
{ /* Constructor do nothing. **/ }
private:
integer mWindowHandle;
virtual void CreateJsonPrivate() = 0;
public:
void CreateJson()
{
CreateJsonPrivate();
std::cout<<"UIData::CreateJson\n";
}
};
class AuthenticateIn : public UIData
{
private:
string mOrigin;
string mLogoURL;
string mUserID;
virtual void CreateJsonPrivate()
{
std::cout<<"AuthenticateIn::CreateJson\n";
}
};
int main()
{
AuthenticateIn* ai = new AuthenticateIn();
ai->CreateJson();
}
Output:
AuthenticateIn::CreateJson
UIData::CreateJson
My question might not be too correct... What I mean is:
class MyClass
{
public:
MyClass()
{
}
virtual void Event()
{
}
};
class FirstClass : public MyClass
{
string a; // I'm not even sure where to declare this...
public:
FirstClass()
{
}
virtual void Event()
{
a = "Hello"; // This is the variable that I wish to pass to the other class.
}
};
class SecondClass : public MyClass
{
public:
SecondClass()
{
}
virtual void Event()
{
if (a == "Hello")
cout << "This is what I wanted.";
}
};
I hope that this makes at least a little sense...
Edit: _This changed to a.
What you need to do is make SecondClass inherit from FirstClass and declare _This as protected.
class FirstClass : public MyClass
{
protected:
string _This;
public:
and
class SecondClass : public FirstClass
What you got doesn't make sense because classes can only see members and functions from their parents (MyClass in your case). Just because two class inherit from the same parent does not mean they have any relation or know anything about each other.
Also, protected means that all classes that inherit from this class will be able to see its members, but nobody else.
I guess that you need something like this (for a sake of simplicity, I've omitted all the unnecessary code):
class Base{
public:
~Base(){}
protected:
static int m_shared;
};
int Base::m_shared = -1;
class A : public Base{
public:
void Event(){
m_shared = 0;
}
};
class B : public Base{
public:
void Event(){
if (m_shared == 0) {
m_shared = 1;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.Event();
b.Event();
return 0;
}
To explain above, I'll explain the static data members:
Non-static members are unique per class instance and you can't share them between class instances. On the other side, static members are shared by all instances of the class.
p.s. I suggest that you read this book (especially Observer pattern). Also note that above code is not thread-safe.