Overriding a protected variable in a dervied class - c++

I have the following project, in which I define a main class called frame, and from that class I derive multiple type of classes. The main class "frame" has a protected variable defined as:
class frame {
protected:
char header[4];
}
And in the derived classes I want the array header to have different size, as the following:
class dervied_frame : public frame {
protected:
char header[8];
}
So my question is it possible to override the protected variable in the derived classes? and how to do that?
Note: I don't want to define the header as a pointer and in then in the constructor I define the size that I want through dynamic allocation.

You could use a template like this:
template <int headerSize>
class frame {
protected:
char header[headerSize];
};
class dervied_frame : public frame<8> {
};
But then every sub-class will have a unique base class so you won't really be able to do anything with a frame *. Depending on what you are using this class for, that restriction could be a deal breaker. You can partially get around this by adding another super-class:
class frame {
public:
void otherMethodsHere();
};
template <int headerSize>
class frameHeader : public frame {
protected:
char header[headerSize];
};
class dervied_frame : public frameHeader<8> {
};

Related

No viable conversion between Derived Class (constructor has parameters) and Base Class (constructor is absent of parameters)

I have an abstract class Handle() containing a handle() method (amongst others). This class is implemented several times, with each class handling a different kind of data (stored as bytes) in a different way, e.g.
class BaseHandle
{
virtual void handle(uint8_t *ptr, uint8_t data_size) = 0;
}
and
class DerivedHandleA : public BaseHandle
{
void handle(uint8_t *ptr, uint8_t data_size)
{
//DO THINGS WITH DATA OF KIND "A"
}
}
class DerivedHandleB : public BaseHandle
{
void handle(uint8_t *ptr, uint8_t data_size)
{
//DO THINGS WITH DATA OF KIND "B"
}
}
My issue is that in handling certain kinds of data the handle() method needs access to instances of other classes to call their member functions, which I would ordinarily pass through the constructor, so currently my code is like this:
class DerivedHandleC : BaseHandle
{
private:
HelperClass helper;
void handle(uint8_t *ptr, uint8_t data_size)
{
//DO THINGS WITH DATA OF KIND "C" WITH FUNCTIONS FROM helper
}
public:
DerivedHandleC(HelperClass helper) : BaseHandle() helper(helper){};
}
The issue arises because I have a std::vector containing each instance of the Handler class, which is iterated through each time I get data to find the correct handler and send on the data. This works fine with DerivedHandle without parameters, but with the constructor with parameters I receive a no viable conversion from 'DerivedHandleC' to 'BaseHandle' when pushing it to my vector, which is understandable.
My question is, what should I be doing instead of passing the parameters I need through the constructor? I would prefer not to simply add the same parameters to all derived classes where they are not needed, though I am aware this would solve my compilation error.
EDITS
Adding std::vector code on request:
Declarations
typedef std::vector<std::unique_ptr<BaseHandler>> HandlerVec;
HandlerVec handlers;
Push back method
registerHandler(std::unique_ptr<BaseHandler> handler)
{
handlers.push_back(std::move(handler));
}
Examples call of pushback
registerHandler(std::make_unique<DerivedHandleA>());
registerHandler(std::make_unique<DerivedHandleC>(helper));
Class types declared using the class keyword have by default private inheritance, compared to class types declared with struct.
Here's an example:
struct A {};
struct B : A {
// inherit publicly from A, the outside world can see the inheritance graph
};
class C : A {
// privately inherit, the outside world cannot see the inheritance
};
To inherit publicly, use a struct or use classes with a specifier to override the default behaviour:
class D : public A {
// inherit publicly
};

C++: Extend member type in derived class

I'd welcome some help with C++ inheritance to get a better grasp of the concept.
Is it possible to "extend" member types when creating a derived class? I think my problem can be best demonstrated by a simple example, where I'd like to extend the class VehicleData with a new double variable:
class VehicleData {
int yearOfManufacture;
//Different routines, for example Serialize(), etc., warranting to create a class for just a bunch of variables
};
class BicycleData:VehicleData {
double frameHeight; //new property that only applies to bicycles
};
//Now I create the actual classes that use the types above
class Vehicle {
VehicleData data;
void PrintData(); //a function that works on basic vehicle data
};
class Bicycle:Vehicle {
BicycleData data; //should copy VehicleData when creating an instance of this class
};
The problem with this approach is that when I code the above and create a Bicycle instance, its BicycleData member hides the already existing VehicleData member.
Is there a way to extend the base class, i.e. simply add a new double variable (to store frame height in this example), and keep the already existing (year of manufacture) data?
As far as I can tell, there is no clean way to do exactly what you want with inheritance alone.
You could create a template out of your base class:
template <typename Data>
class BaseVehicle
{
Data data;
// etc.
};
class Vehicle : BaseVehicle<VehicleData>
{
// etc.
};
class Bicycle : BaseVehicle<BicycleData>
{
// etc.
};
Then the Vehicle and Bicycle classes would contain data field of VehicleData and BicycleData types respectively.
Since in your example Bicycle inherits from Vehicle privately (i.e. there is no support for using Bicycle polymorphically via pointer/reference to Vehicle), this would effectively be identical to what you want to achieve.
If you do want dynamic polymorphism, you should create a separate, preferably abstract, class, defining the interface for your vehicles, e.g.:
class VehicleInterface
{
public:
// Some pure virtual interface methods
virtual void moveTo(const Vector2 position) = 0;
virtual ~VehicleInterface() = default;
};
And then you can have your concrete vehicles inherit and implement this interface:
class Vehicle : BaseVehicle<VehicleData>, public VehicleInterface
{
public:
virtual void moveTo(const Vector2 position) override
{
// implementation for Vehicle
}
};
class Bicycle : BaseVehicle<BicycleData>, public VehicleInterface
{
public:
virtual void moveTo(const Vector2 position) override
{
// implementation for Bicycle
}
};
Then any function, which would like to work with vehicles polymorphically, can just accept a reference or a pointer to VehicleInterface:
void driveToWork(VehicleInterface* vehicle)
{
vehicle->moveTo(getWorkPosition());
// etc.
}
Short answer; Not in the way that you're aiming for, but you can achieve something similar.
Rather than have an instance declared as you have, if you make data a pointer. You can then have BicycleData inherit VehicleData and then just replace data with the new instance in the constructor of the Bicycle.
ie
class Vehicle {
void PrintData();
protected:
void replaceData(std::shared_ptr<VehicleData> d) {
data = d;
}
std::shared_ptr<VehicleData> getData() {
return data;
}
template<class T>
std::shared_ptr<T> getDataAs() {
return std::dynamic_pointer_cast<T>(data);
}
private:
std::shared_ptr<VehicleData> data;
};
class Bicycle:Vehicle {
Bicycle(){replaceData(std::make_shared<BicycleData>());}
std::shared_ptr<BicycleData> getData() {
return getDataAs<BicycleData>();
}
};

Parent class referencing child variable

I have several similar classes inheriting from the same Base-Class/Interface (Base class 1), and they share a couple similar functions, but then also have their own distinct functions. They all also have their own member variables of different classes, and each of those inherits from the same Base-Class/Interface (Base class 2). Is it possible to define a variable in Base class 1, of type Base class 2, then in the actual implementation of classes using Base class 1, have the variable of type Base class 2 be its proper type. Kinda hard to explain, so simplified example below.
//Base-Class 1
class Shape
{
public Shape() {}
ShapeExtra m_var;
//The common functions
public GetVar(){ return m_var; }
}
class Circle : Shape
{
public Circle() { m_var = new CircleExtra(); }
public void CircleFunc()
{
m_var.CircleExtraFunc();
}
}
class Triangle : Shape
{
public Triangle() { m_var = new TriangleExtra(); }
public void TriangleFunc()
{
m_var.TriangleExtraFunc();
}
}
.
.
.
//Base_Class 2
class ShapeExtra
{
public ShapeExtra() {}
}
class CircleExtra : ExtraClass
{
public CircleExtra() {}
void CircleExtraFunc() {//Do stuff}
}
class TriangleExtra : ExtraClass
{
public TriangleExtra() {}
void TriangleExtra() {//Do stuff}
}
.
.
.
So, I need the m_var in the child classes to be kept it as its own unique version. Because right now (w/o the extra CircleExtra m_var;), the GetVar() works, but in CircleFunc, m_var is still type of ShapeExtra, and thus doesn't know that CircleExtraFunc exists. I could cast m_var each time I wanted to do that, but that is repetitive and not worth it in my real-world case. Is there a way to utilize the functions in unique classes based off of ShapeExtra, while keeping the GetVar() function in Shape?
Please ask questions if there is anything I left out.
Simply with inheritance and without using pointers it is not possible, as C++ is a statically-and-strictly-typed language.
You can inherit both the variable and the function, but you'll need to cast function return value.
You can also override the function to make it return the concrete type, but then you have to cast the variable inside the function.
You can also declare the same var with the concrete class in subclasses, but then you just hide the variable in the superclass and inherit nothing.
I'd rather go for a solution using templates. Make the type of the variable a template type and extend the template using a concrete type in subclasses. It'll work perfectly.
It's been a long time since I last programmed in C++ and I beg your pardon if there are errors in the following example. I'm sure you can easily make it work.
template <class S>
class Shape {
S m_var;
//......
public:
S var () {
return m_var;
}
//.......
}
class Circle: Shape <CircleExtra> {
// var method returns CircleExtra
//......
}
Edit:
Regarding some comment, to allow virtual invocation of the method, it is possible to use correlated return types. Something like the following example.
class Shape {
public:
virtual ShapeExtra *var () = 0;
}
template <typename SE>
class ConcreteShape: Shape {
public:
virtual SE *var() {
return &m_var;
}
// Constructor, etc.
private:
SE m_var;
}
Or some variation. Now concrete shapes can benefit from extending the template, as long as SE * is correlated with ShapeExtra * (the type parameter extends ShapeExtra). And you can vall the method transparently through Shape interface.
Using pointers, this is totally possible.
Using your example, you could do something like this:
#include <iostream>
#include <memory>
using namespace std;
//Extras
class ShapeExtra
{
public:
ShapeExtra() {}
void ShapeFunc() { std::cout << "Shape"; }
virtual ~ShapeExtra() = default; //Important!
};
class Shape
{
public:
std::unique_ptr<ShapeExtra> m_var;
//require a pointer on construction
//make sure to document, that Shape class takes ownership and handles deletion
Shape(ShapeExtra* p):m_var(p){}
//The common functions
ShapeExtra& GetVar(){ return *m_var; }
void ShapeFunc() {m_var->ShapeFunc();}
};
class CircleExtra : public ShapeExtra
{
public:
void CircleExtraFunc() {std::cout << "Circle";}
};
class Circle : public Shape
{
CircleExtra* m_var;
public:
Circle() : Shape(new CircleExtra()) {
m_var = static_cast<CircleExtra*>(Shape::m_var.get());
}
void CircleFunc()
{
m_var->CircleExtraFunc();
}
};
int main() {
Circle c;
//use the ShapeExtra Object
c.GetVar().ShapeFunc();
//call via forwarded function
c.ShapeFunc();
//call the circleExtra Function
c.CircleFunc();
return 0;
}
Test it on ideone
Note the use of pointers and a virtual destructor:
By using a virtual destructor in the ShapeExtra base class, you make it possible to destruct an object of any derived class, using a ShapeExtra*. This is important, because
by using a std::unique_ptr<ShapeExtra> instead of a plain C-pointer, we make sure that the object is properly deleted on destruction of Shape.
It is probably a good idea to document this behaviour, i.e. that Shape takes the ownership of the ShapeExtra*. Which especially means, that we do not delete CirleExtra* in the Circle destructor
I decided here to require the ShapeExtra* on construction, but its also possible to just use std::unique_ptr::reset() later and check for nullptr on dereferencing Shape::m_var
Construction order is this: On calling the constructor of Circle, we first create a new CircleExtra which we pass to Shape before finally the constructor of Circle is executed.
Destruction order is Circle first (was created last), then Shape which also destructs the ShapeExtra for us, including (via virtual function) the CircleExtra
I would recommend the following approach:
class ShapeExtra
{
public:
virtual ~ShapeExtra() { }
virtual void SomeCommonShapeFunc() { std::cout << "Shape"; }
};
class Shape
{
public:
virtual ShapeExtra &GetVar() = 0; // Accessor function.
};
Note that the class Shape does not have any data members at all. After that for each derived class you need:
class CircleExtra : public ShapeExtra
{
public:
void SomeCommonShapeFunc() { std::cout << "Circle"; }
};
class Circle : public Shape
{
CircleExtra m_var; // Data member with circle specific class.
public:
virtual ShapeExtra &GetVar() { return m_var; }
};
Implementation of virtual method in Circle will return reference to the base class ShapeExtra. This will allow using this extra in the base class.
Note that pointers and templates are not used at all. This simplifies the overall design.

Is there anything better than a metafactory to work around constructor injection into derived classes in CRTP?

In the CRTP, I want to inject the constructor into the derived class, cleanly - without use of macros and without writing it out. It seems it's impossible, so I've come up with some workarounds.
First, there's an underlying event class (QEvent) that should have a unique integer type tag for every derived class (see rationale). You obtain it by calling a registration function It's easy enough to create a CRTP wrapper that will hide this from you:
template <typename Derived> class EventWrapper : public QEvent {
public:
EventWrapper() : QEvent(staticType()) {}
static QEvent::Type staticType() {
static QEvent::Type type = static_cast<QEvent::Type>(registerEventType());
return type;
}
};
class MyEvent1 : public EventWrapper<MyEvent1> {}; // easy-peasy
class MyEvent2 : public EventWrapper<MyEvent2> {};
Note that MyEvent1::staticType() != MyEvent2::staticType(): registerEventType() returns unique types each time it's called.
Now I want the event class to carry some data:
template <typename Derived> class StringEvent : public EventWrapper<D> {
std::string m_str;
public:
explicit StringEvent(const std::string & str) : m_str(str) {}
std::string value() const { return m_str; }
};
But here we run into a problem: we need to manually define the constructor in each of the derived classes. The whole point here is that creation of such classes should be easy, as there may be many different string-carrying event types. But it's anything but easy:
class MyEvent3 : public StringEvent<MyEvent3> {
public: MyEvent3(std::string s) : StringEvent(s) {}
};
This obviously gets old real quick, even with C++11 constructor forwarding:
class MyEvent3 : public StringEvent<MyEvent3> { using StringEvent::StringEvent; };
What we'd want is a way of injecting this constructor into the derived class, or avoiding doing so while still providing for ease of use. Sure you can hide it in a preprocessor macro, but I hate those macros, they are a maintenance pain as they introduce new names for very simple concepts.
We can of course use a dummy type. Note that there's no need for a definition of the dummy type. It's only a name to be used as the type argument.
// Pre-C++11
class DummyEvent3;
typedef StringEvent<DummyEvent3> MyEvent3;
// C++11
class DummyEvent3;
using MyEvent3 = StringEvent<DummyEvent3>;
Another solution would be to use an int template argument and use an enum value, but this brings back the uniqueness issue that got solved by using the registerEventType() in the first place. It'd be no fun to guarantee that a large program is correct. And you'd still need to spell out the enum.
So, I've come up with a metaprogram class that I'll call a metafactory, that can produce the ready-to-use StringEvent classes for us, while keeping it all to one type definition:
// the metafactory for string events
template <typename Derived> class StringEventMF {
public:
class Event : public EventWrapper<Derived> {
std::string m_str;
public:
explicit Event(const std::string & val) : m_str(val) {}
std::string value() const { return m_str; }
};
};
or simply
template <typename Derived> class StringEventMF {
public:
typedef StringEvent<Derived> Event;
};
This is used like:
class Update : public StringEventMF<Update> {};
class Clear : public StringEventMF<Clear> {};
void test() {
Update::Event * ev = new Update::Event("foo");
...
}
The classes you use are Update::Event, Clear::Event. The Update and Clear are metafactories: they generate the desired event class for us. The derivation from the metafactory sidesteps derivation from the concrete class type. The metafactory type gives the unique type discriminator needed to create unique concrete class types.
The questions are:
Is there any "cleaner" or "more desirable" way of doing it? Ideally, the following non-working pseudocode would be my ideal way of doing it - with zero repetition:
class UpdateEvent : public StringEvent <magic>;
The name of the derived class appears only once, and the name of the base concept StringEvent appears only once, too. The CRTP requires the class name to appear twice - so far I think it's acceptable, but my metaprogramming-fu is in tatters. Again, I want a preprocessor-less solution, it'd be a no-brainer otherwise.
Is the name metafactory my original invention (ha ha), or is it merely my google-Fu that's lacking? This metafactory pattern seems to be quite flexible. It's easy to compose metafactories by multiple derivation. Say you wanted an Update::Event made by one factory, and Update::Foo made by another.
This question is motivated by this answer. Note: in real code I'd be using QString, but I'm trying to keep it as generic as possible.
I think what you're looking for might be just using placement new to instantiate the base class.
The derived class won't be constructable because unless they will create a matching constructor.
But, they don't have to be constructable, you could use them anyway. (It could still be destructable).
template <class T>
class Base
{
protected: Base(int blah) { }
public: static T* CreateInstance(int data) {
T* newOjectBlock = reinterpret_cast<T*>(::operator new(sizeof(T))); // allocate enough memory for the derived class
Base* newBasePlace = (Base*)(newOjectBlock); //point to the part that is reseved for the base class
newBasePlace= new ((char*)newBasePlace) Base(data); //call the placement new constrcutor for the base class
return newOjectBlock;
}
};
class Derived : public Base<Derived> {}
Then let the CRTP base class construct the derived class like this:
Derived* blah = Derived::CreateInstance(666);
If anyone ever wants to initialize the derived class, they should either make a matching constructor that calls the base class constructor.
OR, just make an .init() method that initiates its members, and will be called after the instance is created.
OR, we can think of something else, this is just an idea of a concept.
Yochai Timmer has come up with an alternative way of approaching the problem. Instead of having to forward the constructor from the data carrier class, he exposes a factory method that produces pseudo-derived classes. As it invokes undefined behavior, I'm not particularly keen on it.
Expanding a bit on the original metafactory concept, it's possible to make generic metafactory that can be used to make unique event types that wrap "any" data-carrying class.
The approach for C++11 uses constructor forwarding so that plain non-template data carrier classes can be used. The approach for C++98 requires a templated data carrier class and, internally, a bit more gymnastics, but it works as well.
The event classes can't be further derived from. This is necessary since the derived classes would all share the value of staticType, and that can't be allowed, as DyP duly noted in the comments.
To test the code, you need the event wrapper, the metafactory and data carrier selected for your variant of C++, and the test/usage part.
The Event Wrapper (Common Code)
In either case, our basic event wrapper CRTP class that generates a unique static type value for the event is:
// A type-identifier-generating wrapper for events. It also works with RTTI disabled.
template <typename Derived> class EventWrapper : public QEvent {
public:
EventWrapper() : QEvent(staticType()) {}
static QEvent::Type staticType() {
static QEvent::Type type = static_cast<QEvent::Type>(registerEventType());
return type;
}
static bool is(const QEvent * ev) { return ev->type() == staticType(); }
static Derived* cast(QEvent * ev) { return is(ev) ? static_cast<Derived*>(ev) : 0; }
};
Note that it also provides a cast-to-derived method. You'd use it in an event handler, given a pointer to a base event class:
void MyClass::customEvent(QEvent* event) {
if (MyEvent::is(event)) {
auto myEvent = MyEvent::cast(event);
// use myEvent to access data carrying members etc)
}
}
The C++98 Metafactory
The Carrier is a parametrized data carrier class, such as StringData below.
// The generic event metafactory
template <typename Derived, template <typename> class Carrier> class EventMF {
class EventFwd;
class Final;
class FinalWrapper : public EventWrapper<EventFwd>, public virtual Final {};
public:
// EventFwd is a class derived from Event. The EventWrapper's cast()
// will cast to a covariant return type - the derived class. That's OK.
typedef Carrier<FinalWrapper> Event;
private:
class EventFwd : public Event {};
class Final {
friend class FinalWrapper;
friend class Carrier<FinalWrapper>;
private:
Final() {}
Final(const Final &) {}
};
};
The EventFwd class is needed so that we have something sane to pass to the EventWrapper template as the derived class, so that the cast() static method will work. The FinalWrapper is there since in pre-C++11 we can't friend typecasts.
Now for the parametrized data carrier. It'd be the same as for the C++11 variant below except for needing to have a parametrized base class.
// A string carrier
template <typename Base> class StringData : public Base {
QString m_str;
public:
explicit StringData(const QString & str) : m_str(str) {}
QString value() const { return m_str; }
};
The C++11 MetaFactory
// The generic metafactory for unique event types that carry data
template <typename Derived, class Data> class EventMF {
class Final;
EventMF();
EventMF(const EventMF &);
~EventMF();
public:
class Event : public EventWrapper<Event>, public Data, private virtual Final {
public:
template<typename... Args>
Event(Args&&... args): Data(std::forward<Args>(args)...) {}
};
private:
class Final {
friend class Event;
private:
Final() {}
Final(const Final &) {}
};
};
The gymanstics with forward-declaration of the Final class are there since forward-declaring the Event class is more typing.
The data carrier is as simple as it gets:
// A string carrier
class StringData {
QString m_str;
public:
explicit StringData(const QString & str) : m_str(str) {}
QString value() const { return m_str; }
};
Usage & Tests (Common Code)
And now we can use the generic metafactory to make some concrete metafactories, and then to make the event classes we need. We create two unique event types that carry the data. Those event classes have unique staticType()s.
// A string event metafactory
template <typename Derived> class StringEventMF : public EventMF<Derived, StringData> {};
class Update : public EventMF<Update, StringData> {}; // using generic metafactory
class Clear : public StringEventMF<Clear> {}; // using specific metafactory
#if 0
// This should fail at compile time as such derivation would produce classes with
// duplicate event types. That's what the Final class was for in the matafactory.
class Error : public Update::Event { Error() : Update::Event("") {} };
#endif
int main(int, char**)
{
// Test that it works as expected.
Update::Event update("update");
Clear::Event clear("clear");
Q_ASSERT(Update::Event::staticType() != Clear::Event::staticType());
Q_ASSERT(Update::Event::staticType() == Update::Event::cast(&update)->staticType());
qDebug() << Update::Event::cast(&update)->value();
Q_ASSERT(Update::Event::cast(&clear) == 0);
qDebug() << Clear::Event::cast(&clear)->value();
Q_ASSERT(Clear::Event::cast(&update) == 0);
}

Class within class - incomplete type is not allowed

class Publicatie{
public:
class Carte : public Publicatie{
private:
char* autor;
};
class Revista : public Publicatie{
private:
char* frecventa_aparitie;
int numar;
};
private:
int cota;
char* titlu;
char* editura;
int anul_aparitiei;
int tiraj;
Carte* c;
Revista* r;
public:
//some methods...
}
This is the code, i'm declaring the class Carte and Revista inside the class Publicatie and i need to have private members Carte and Publicatie. I really don't know how to do the design with inheritance with these classes. I get the error in the title for the inheritance :public Publicatie and i thought that it will work because the class is already created ( even though it's private members were not created yet).
your design is wrong. you're trying to define a class, and in it's definition you're trying to use from itself; it is a logical paradox.
from what i can understand from your code, you're trying to create a class named Publicatie that represents a publication (or a post) and it has two other variants, named Carte and Revista. if this is the case, why the Publicatie needs to have two private members of type Carte and Revista? maybe you can remove these two members from it.
or maybe you can move some of their shared members (such as titlu, tiraj and...) to another class that is abstract, and then define Publicatie, Carte and Revista such that all of them inherit from the same parent class.
hope these work.
You can only inherit from a class that is a complete type. However, you don't need to have the nested class definition inside your ambient class definition. Instead, you can do it like so:
struct Foo
{
struct Bar;
Bar * p;
int get();
};
struct Foo::Bar : Foo
{
int zip() { return 4; }
};
int Foo::get() { return p->zip(); }