Is there anyway to have a sort of virtual static member in C++?
For example:
class BaseClass {
public:
BaseClass(const string& name) : _name(name) {}
string GetName() const { return _name; }
virtual void UseClass() = 0;
private:
const string _name;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass("DerivedClass") {}
virtual void UseClass() { /* do something */ }
};
I know this example is trivial, but if I have a vector of complex data that is going to be always the same for all derived class but is needed to be accessed from base class methods?
class BaseClass {
public:
BaseClass() {}
virtual string GetName() const = 0;
virtual void UseClass() = 0;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() {}
virtual string GetName() const { return _name; }
virtual void UseClass() { /* do something */ }
private:
static const string _name;
};
string DerivedClass::_name = "DerivedClass";
This solution does not satify me because I need reimplement the member _name and its accessor GetName() in every class. In my case I have several members that follows _name behavior and tenths of derived classes.
Any idea?
Here is one solution:
struct BaseData
{
const string my_word;
const int my_number;
};
class Base
{
public:
Base(const BaseData* apBaseData)
{
mpBaseData = apBaseData;
}
const string getMyWord()
{
return mpBaseData->my_word;
}
int getMyNumber()
{
return mpBaseData->my_number;
}
private:
const BaseData* mpBaseData;
};
class Derived : public Base
{
public:
Derived() : Base(&sBaseData)
{
}
private:
static BaseData sBaseData;
}
BaseData Derived::BaseData = { "Foo", 42 };
It seems like the answer is in the question - the method you suggested seems to be the right direction to go, except that if you have a big number of those shared members you might want to gather them into a struct or class and past that as the argument to the constructor of the base class.
If you insist on having the "shared" members implemented as static members of the derived class, you might be able to auto-generate the code of the derived classes. XSLT is a great tool for auto-generating simple classes.
In general, the example doesn't show a need for "virtual static" members, because for purposes like these you don't actually need inheritance - instead you should use the base class and have it accept the appropriate values in the constructor - maybe creating a single instance of the arguments for each "sub-type" and passing a pointer to it to avoid duplication of the shared data. Another similar approach is to use templates and pass as the template argument a class that provides all the relevant values (this is commonly referred to as the "Policy" pattern).
To conclude - for the purpose of the original example, there is no need for such "virtual static" members. If you still think they are needed for the code you are writing, please try to elaborate and add more context.
Example of what I described above:
class BaseClass {
public:
BaseClass(const Descriptor& desc) : _desc(desc) {}
string GetName() const { return _desc.name; }
int GetId() const { return _desc.Id; }
X GetX() connst { return _desc.X; }
virtual void UseClass() = 0;
private:
const Descriptor _desc;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(Descriptor("abc", 1,...)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass("Wowzer", 843,...) {}
virtual void UseClass() { /* do something */ }
};
I'd like to elaborate on this solution, and maybe give a solution to the de-initialization problem:
With a small change, you can implement the design described above without necessarily create a new instance of the "descriptor" for each instance of a derived class.
You can create a singleton object, DescriptorMap, that will hold the single instance of each descriptor, and use it when constructing the derived objects like so:
enum InstanceType {
Yellow,
Big,
BananaHammoc
}
class DescriptorsMap{
public:
static Descriptor* GetDescriptor(InstanceType type) {
if ( _instance.Get() == null) {
_instance.reset(new DescriptorsMap());
}
return _instance.Get()-> _descriptors[type];
}
private:
DescriptorsMap() {
descriptors[Yellow] = new Descriptor("Yellow", 42, ...);
descriptors[Big] = new Descriptor("InJapan", 17, ...)
...
}
~DescriptorsMap() {
/*Delete all the descriptors from the map*/
}
static autoptr<DescriptorsMap> _instance;
map<InstanceType, Descriptor*> _descriptors;
}
Now we can do this:
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.BananaHammoc)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.Yellow)) {}
virtual void UseClass() { /* do something */ }
};
At the end of execution, when the C runtime performs uninitializations, it also calls the destructor of static objects, including our autoptr, which in deletes our instance of the DescriptorsMap.
So now we have a single instance of each descriptor that is also being deleted at the end of execution.
Note that if the only purpose of the derived class is to supply the relevant "descriptor" data (i.e. as opposed to implementing virtual functions) then you should make do with making the base class non-abstract, and just creating an instance with the appropriate descriptor each time.
I agree with Hershi's suggestion to use a template as the "base class". From what you're describing, it sounds more like a use for templates rather then subclassing.
You could create a template as follows ( have not tried to compile this ):
template <typename T>
class Object
{
public:
Object( const T& newObject ) : yourObject(newObject) {} ;
T GetObject() const { return yourObject } ;
void SetObject( const T& newObject ) { yourObject = newObject } ;
protected:
const T yourObject ;
} ;
class SomeClassOne
{
public:
SomeClassOne( const std::vector& someData )
{
yourData.SetObject( someData ) ;
}
private:
Object<std::vector<int>> yourData ;
} ;
This will let you use the template class methods to modify the data as needed from within your custom classes that use the data and share the various aspects of the template class.
If you're intent on using inheritance, then you might have to resort to the "joys" of using a void* pointer in your BaseClass and dealing with casting, etc.
However, based on your explanation, it seems like you need templates and not inheritance.
#Hershi: the problem with that approach is that each instance of each derived class has a copy of the data, which may be expensive in some way.
Perhaps you could try something like this (I'm spit-balling without a compiling example, but the idea should be clear).
#include <iostream>
#include <string>
using namespace std;
struct DerivedData
{
DerivedData(const string & word, const int number) :
my_word(word), my_number(number) {}
const string my_word;
const int my_number;
};
class Base {
public:
Base() : m_data(0) {}
string getWord() const { return m_data->my_word; }
int getNumber() const { return m_data->my_number; }
protected:
DerivedData * m_data;
};
class Derived : public Base {
public:
Derived() : Base() {
if(Derived::s_data == 0) {
Derived::s_data = new DerivedData("abc", 1);
}
m_data = s_data;
}
private:
static DerivedData * s_data;
};
DerivedData * Derived::s_data = 0;
int main()
{
Base * p_b = new Derived();
cout getWord() << endl;
}
Regarding the follow-up question on deleting the static object: the only solution that comes to mind is to use a smart pointer, something like the Boost shared pointer.
It sounds as if you're trying to avoid having to duplicate the code at the leaf classes, so why not just derive an intermediate base class from the base class. this intermediate class can hold the static data, and have all your leaf classes derive from the intermediate base class. This presupposes that one static piece of data held over all the derived classes is desired, which seems so from your example.
Related
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.......
I'm trying to make an abstract class, and one of the methods that its children must override should return an instance of the child class.
class JsonSerializable {
public:
virtual <child_of_JsonSerializable> fromJson(string jsonStr) const = 0;
};
class ConcreteSerializable : public JsonSerializable {
public:
ConcreteSerializable fromJson(string jsonStr) const {
return ConcreteSerializable();
}
};
I tried using templates following this answer, but I get an error that templates may not be virtual.
Is there a way to do what I'm looking for without using raw pointers as the return type?
You cannot create an object of an abstract type. And because you cannot create such an object, you also cannot return it. This is the reason why all examples returning a base/derived object, always return a pointer or some reference to the base class
struct B {
virtual B *fromJson(const std::string &jsonStr) const = 0;
};
struct D : public B {
D(const std::string &jsonStr);
D *fromJson(const std::string &jsonStr) const;
};
D *D::fromJson(const std::string &jsonStr) const
{
return new D(jsonStr);
}
Are you trying to implement something that historically was done using CRTP?
struct Interface {
virtual Interface *inflate(std::string const &json) = 0;
virtual ~Interface() {}
};
template<typename Child> struct Base: public Interface {
Interface *inflate(std::string const &json) { return new Child(json); }
};
struct Child: public Base<Child> {
Child(std::string const &json);
};
Consider the following:
class Base {
public:
virtual std::string getName() = 0;
...
};
class Derived1 : public Base {
public:
static std::string getClassName() { return("Derived1"); }
std::string getName() { return("Derived1"); }
...
};
class Derived2 : public Base {
public:
static std::string getClassName() { return("Derived2"); }
std::string getName() { return("Derived2"); }
...
};
The idea is that if you have the derived class passed as, say, a template parameter, then you can get its class name via getClassName, while if you have it passed as a pointer to base class, you can get the name via getName.
I have seem a lot of similar questions to this here but all of them seem to ask stuff like "how do I use a static virtual", "why don't static virtuals exist" and various stuff like that, and the answers seem to address that more than what I think the real underlying problem is, which is: how can I avoid having to repeat myself with that code and mentioning the name twice while using as little boilerplate as possible? (Don't Repeat Yourself, or DRY Rule)
I don't want a macro, either.
First off, you can re-use getClassName in getName:
class Derived1 : public Base {
public:
static std::string getClassName() { return("Derived1"); }
std::string getName() override { return getClassName(); }
...
};
Now, all definitions of getName() are identical, so you can put them in a macro to save on typing (and make them more future-proof):
#define GET_NAME() std::string getName() override { return getClassName(); }
class Derived1 : public Base {
public:
static std::string getClassName() { return("Derived1"); }
GET_NAME()
...
};
Or you can bundle getClassName in there as well:
#define GET_NAME(maName) \
static std::string getClassName() { return(maName); } \
std::string getName() override { return getClassName(); }
class Derived1 : public Base {
public:
GET_NAME("Derived1")
...
};
You say "I don't want a macro, either," but macros are a good tool for that, and I wouldn't see a single problem with using them like this. However, if that is not what you want, you can do it without them as well:
template <class Self>
struct GetName : public Base
{
std::string getName() override { return Self::getClassName(); }
};
class Derived1 : public GetName<Derived1> {
public:
static std::string getClassName() { return("Derived1"); }
...
};
class Derived2 : public GetName<Derived2> {
public:
static std::string getClassName() { return("Derived2"); }
...
};
Don't fear data:
class Base {
public:
std::string const Name;
Base(std::string Name) : Name(Name) { }
};
class Derived1 : public Base {
public:
static const std::string Name;
Derived1() : Base { Name } { }
};
const std::string Derived1::Name { "Derived1" }
Make a separate base class that has the single responsibility of providing a class name string:
class FakeRTTI
{
std::string class_name;
public:
FakeRTTI( std::string className ) : class_name(className) {}
getClassName() { return class_name; }
}
With which you can then do this in all classes that need your fake, inefficient, explicit, string-based RTTI:
class Bla : public FakeRTTI
{
public:
Bla() : FakeRTTI("Bla") {}
}
Pro's:
DRY: there is only one ever use of the string "Bla", in its constructor.
Single Responsibility Principle
No virtual function calls
Cons:
Multiple inheritance (is this is con, really?)
You're not using the efficient, standard, C++-based RTTI.
You're still using RTTI (it might well not be feasible to get rid of it, but it is a sign of code smell all the smell).
Another possible solution uses traits and type erasure as in the following example:
#include<string>
#include<iostream>
template<typename> struct NameTraits;
template<typename T>
struct tag {};
class Base {
using func = std::string(*)(void);
template<typename T>
static std::string name() {
return NameTraits<T>::name;
}
public:
template<typename T>
Base(tag<T>): nameF{&name<T>} {}
std::string getName() {
return nameF();
}
private:
func nameF;
};
struct Derived1: Base {
Derived1(): Base{tag<Derived1>{}} {}
};
struct Derived2: Base {
Derived2(): Base{tag<Derived2>{}} {}
};
template<> struct NameTraits<Derived1> { static constexpr char *name = "Derived1"; };
template<> struct NameTraits<Derived2> { static constexpr char *name = "Derived2"; };
int main() {
Base *base = new Derived1;
// Using base class
std::cout << base->getName() << std::endl;
// Using directly the type
std::cout << NameTraits<Derived2>::name << std::endl;
}
Pros:
Name is no longer part of the class and you can easily define a common trait for a family of classes (use simply the same tag for all of them)
You don't have any virtual method
You don't need two methods that do almost the same thing
Cons:
You have to explicitly specify the tag that carries the type to be used during construction
I'm trying to create a class that serves as a base object, which will then be sub-classed (=implemented) to serve various purposes.
I want to define one or more pure virtual functions, so that however subclasses the base class, is required and does not forget to implement them.
There is one caveat, the pure virtual function's signature includes the type of the base object. Once sub-classed, the function definition doesn't match the base classes definition anymore of course. E.g.:
class BaseItem
{
public:
virtual std::string getDifferences(const BaseItem& item) = 0;
}
So, in the derived class I'd like to do:
class DerivedClass : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
std::string derivedItemCustomObject;
}
which of course the compiler won't accept. I could make it a BaseItem of course, but then I can't utilize any objects in the derived class.
Do I have to use casting to accomplish this?
Please let me know if my intent/question is not clear.
There is NO need to change the function signature. Look at following:
class BaseItem
{public:
virtual std::string getDifferences(const BaseItem& item) = 0;
};
class DerivedClass : public BaseItem
{public:
virtual std::string getDifferences(const BaseItem& item) // keep it as it's
{
const DerivedClass& derivedItem = static_cast<const DerivedClass&>(item);
}
};
Can use static_cast<> without any fear because, DerivedClass::getDifferences() is called only for DerivedClass object. To illustrate,
BaseItem *p = new DerivedClass;
DerivedClass obj;
p->getDifferences(obj); // this always invoke DerivedClass::getDifferences
If you worry that sometime you might end up passing any other derived class object as an argument to the method, then use dynamic_cast<> instead and throw exception if that casting fails.
It's unclear what you're trying to achieve. Suppose that the compiler allowed you to do this (or you do this by the means of a cast), then it would open the following hole in the type system:
class BaseItem
{
public:
virtual std::string getDifferences(const BaseItem& item) = 0;
};
class DerivedClass : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass& item)
{
item.f();
// ...
}
void f() const {}
};
class DerivedClass2 : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass2& item) { ... }
};
void g()
{
BaseItem* x = new DerivedClass;
// oops, calls DerivedClass::f on an instance of DerivedClass2
x->getDifferences(DerivedClass2());
}
Your design is probably wrong.
I assume that the compiler accept but DerivedClass::getDifferences doesn't override BaseItem::getDifferences. Here is a way to achieve what you apparently want
template <typename T>
class DerivedHelper: public BaseItem {
public:
virtual std::string getDifferences(const BaseItem& item) {
getDifferences(dynamic_cast<const T&>(item));
}
virtual std::string getDifferences(const T& item) = 0;
};
class DerivedClass : public DerivedHelper<DerivedClass>
{
public:
// not more needed but providing it will hide getDifferences(const BaseItem& item)
// helping to statically catch some cases where a bad argument type is used.
virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
std::string derivedItemCustomObject;
};
but be aware that there is a runtime check which will throw exceptions if the argument isn't of the correct class.
One way to accomplish this is to use a template and have the parameter be the type of the derived type
template <typename T>
class BaseItem {
public:
virtual std::string getDifferences(const T& item) = 0;
};
class DerivedClass : public BaseItem<DerivedClass> {
public:
virtual std::string getDifferences(const DerivedClass& item) {
// Implement it here
}
};
You should use cast from BaseItem to DerivedClass + runtime check if given BaseItem is a DerivedClass instance.
I think I messed up somehow in my design because I want to keep a vector of various object types. These types all share a common base class. Example:
Class Buick: AmericanCar
{
}
Class Ford: AmericanCar
{
}
then I did:
vector<AmericanCar*> cars_i_own;
Now, I have my vector of pointers but I don't have the derived class which is what I need. I thought about adding a GetType/SetType function to the base class and then use a dynamic cast. This is clunky though. Did i use the wrong design for this?
Well, what are you trying to do with it? Get the name or cost? You would have something like:
class Car
{
public:
virtual ~Car(void) {}
virtual std::string location(void) const = 0;
virtual std::string name(void) const = 0;
virtual double cost(void) const = 0;
}
class AmericanCar
{
public:
virtual ~AmericanCar(void) {}
virtual std::string location(void) const
{
return "America";
}
}
class Buick : public AmericanCar
{
public:
virtual std::string name(void) const
{
return "Buick";
}
virtual double cost(void) const
{
return /* ... */;
}
}
class Ford : public AmericanCar
{
public:
virtual std::string name(void) const
{
return "Ford";
}
virtual double cost(void) const
{
return /* ... */;
}
}
Now you can call these methods polymorphically.
This is somewhat strange, though. You don't need a different class to store names and cost like this:
class Car
{
public:
Car(const std::string& pLocation,
const std::string& pName,
double pCost) :
mLocation(pLocation),
mName(pName),
mCost(pCost)
{
}
const std::string& location(void) const
{
return mLocation;
}
void location(const std::string& pLocation)
{
mLocation = pLocation;
}
const std::string& name(void) const
{
return mName;
}
void name(const std::string& pName)
{
mName = pName;
}
const double cost(void) const
{
return mCost;
}
void cost(double pCost)
{
mCost = pCost;
}
private:
std::string mLocation;
std::string mName;
double mCost;
}
// make cars
std::vector<Car> cars;
cars.push_back(Car("America", "Buick", /* ... */));
The purpose of inheritance / polymorphism is so you don't need to care which derived type you are dealing with.
In particular I think storing data, such as make of car, country of origin etc, encoded in a class hierarchy doesn't seem to be particularly beneficial. Does an AmericanCar do something fundamentally different from, say, a Japanese car (other than consuming more fuel, which again can be better stored in a data member)?
Why do you need to know the derived class? Normally you would have virtual functions to take care of any behavior differences between the two derived classes.
The goal is that the code using the parent class shouldn't have to know the exact class it's working with.
You can use typeid to determine the derived class:
struct Base
{
virtual ~Base() {}
};
struct Derived : public Base { };
int main()
{
Base* b = new Derived();
std::cout << typeid(*b).name() << std::endl;
}
This outputs: "Derived".
But, usually with polymorphism the point is that you shouldn't be concerned with this. You simply call a base-class member function and the proper derived-class member function is called at runtime.