Is an object valid in serialized form? c++/inheritance/serialization - c++

I'm asking this because even tho it seems to work, I feel like it shouldn't. The goal is to have a collection of objects kept alive, and general access to them. This is what I have at the moment:
Take a base pointer access:
struct base { virtual void tick() = 0; }; //ptr access
With different types that inherit from it:
struct :public base
{
void tick() { cout << "im type 1" << endl; }
}type1;
struct :public base
{
void tick() { cout << "im type 2" << endl; }
}type2;
Then a container class that should be able to store any amount of these serialized:
class control
{
struct xtype //struct for organizing objects
{
vector<char>charbuf; //serialized object
}xtype_template;
vector<xtype>xtype_vec;
public:
template<typename T> base* tell_to(T &input) //take object, return (base*)
{
xtype_template.charbuf.resize(sizeof(input));
memcpy(xtype_template.charbuf.data(), (char*)&input, sizeof(input));
xtype_vec.push_back(xtype_template); //push back with template after filling
return (base*)xtype_vec[xtype_vec.size() - 1].charbuf.data(); //pointer to data
}
}xcontainer; //container object
Then call:
auto ptr = controller.tell_to(type1); //becomes base*
auto ptr2 = controller.tell_to(type2);
And you can access either static-sized serialized object, as well as its states, by doing:
ptr->tick(); //which will output "im type 1" to console
ptr2->tick() //"im type 2"
But is this legal? Do these serialized versions have an actual type? Is accessing a serialized object directly with a base pointer illegal or wrong?
Closest probable answer: as the return on is_trivially_copyable show false, objects might not be safe to manage after getting base inheritance.
Follow up: This approach seems to work, and fiddling with is_trivially_copyable, seems to suggest that making an object inherit methods from, makes it unsafe. Basic methods do not make it unsafe however, and that makes me wonder if the safety only applies to exporting between systems, saving to file, or transferring over the network. Maybe the check just assumes the virtual reference makes them unsafe?
Follow up 2: If the characters remain in the same spot in memory, does it matter how they are accessed? Id wager that the only real problem with this approach, is if the objects stored were to have elements that would change their size after being stored.

What you are doing is illegal. You can only memcpy an object as an array of chars when the object is TriviallyCopyable. And your object is not, since it has virtual functions.
Instead of doing this, you should simply store a (unique) pointer to newly allocated object, and avoid any casts to enforce hierarchy. Like this:
class xtype
{
std::unique_ptr<base> ptr;
public:
template<typename T> base* serial_acc(T &input) //take object, return (base*)
{
static_assert(std::is_base_of<base, T>::value, "Please use proper type");
ptr = std::make_unique<base>(input);
return ptr;
}
} xcontainer;

Working example given by user Andy Prowl
#include <vector>
#include <memory>
#include <iostream>
using namespace std;
struct base
{
virtual void tick() = 0;
};
struct type1 : base
{
virtual void tick() override { cout << "im type 1"<<endl; }
};
struct type2 : base
{
virtual void tick() override { cout << "im type 2" << endl; }
};
struct controller
{
vector<unique_ptr<base>> objects;
void cycle_tick(){ for (auto const& ptr : objects)ptr->tick();}
void add_object(unique_ptr<base> obj){ objects.emplace_back(move(obj));}
};
int main()
{
auto t1 = unique_ptr<type1>(new type1);
auto t2 = unique_ptr<type2>(new type2);
controller ctrl_object;
c.add_object(move(t1));
c.add_object(move(t2));
ctrl_object.cycle();
}

Related

C++ change parent class based on option

There is a Student class inherited from Person.
And there is Student class inherited from University.
I want to change the parent class Person, University based on the option without rewriting Student such as Student1 and Student2 (because student class is very complicated).
Here is the example code.
class Person {
void f() {printf("I'm person")}
};
class University {
void f() {printf("I'm university")}
};
class Student1 : public Person {
void g() {f()}
};
class Student2 : public University {
void g() {f()} // I don't wan't to rewrite this!
};
if (option.person) {
Student1 student;
}
else {
Student2 student;
}
Since we can't know what option.person is at compile-time, we need to find a way to work around that at runtime.
One option for doing so is std::variant, which can store any number of different types; but does so at the cost of always having the same size as the largest templated type.
As an example, if I did this:
std::variant<char, int> myVariant = '!';
Even though myVariant holds a char (1 byte), it uses 4 bytes of RAM because an int is 4 bytes.
Using Variants
Rather than inheriting from different objects that do not share a common base at compile-time, we can maintain the 'base' type as a variable within Student instead.
#include <iostream>
#include <variant>
#include <concepts>
class Person {
public:
void f()
{
std::cout << "I'm a person!\n";
}
};
class University {
public:
void f()
{
std::cout << "I'm a university!\n";
}
};
class Student {
public:
using variant_t = std::variant<Person, University>;
variant_t base;
// Here we accept an rvalue of any type, then we move it to the 'base' variable.
// if the type is not a Person or University, a compiler error is thrown.
Student(auto&& owner) : base{ std::move(owner) } {}
void g()
{
// METHOD 1: Using std::holds_alternative & std::get
// This has the advantage of being the simplest & easiest to understand.
if (std::holds_alternative<Person>(base))
std::get<Person>(base).f();
else if (std::holds_alternative<University>(base))
std::get<University>(base).f();
// METHOD 2: Using std::get_if
// This has the advantage of being the shortest.
if (auto* person = std::get_if<Person>(&base))
person->f();
else if (auto* university = std::get_if<University>(&base))
university->f();
// METHOD 3: Using std::visit
// This has the advantage of throwing a meaningful compiler error if-
// -we modify `variant_t` and end up passing an unhandled type.
std::visit([](auto&& owner) {
using T = std::decay_t<decltype(owner)>;
if constexpr (std::same_as<T, Person>)
owner.f(); //< this calls `Person::f()`
else if constexpr (std::same_as<T, University>)
owner.f(); //< this calls `University::f()`
else static_assert(false, "Not all potential variant types are handled!");
}, base);
}
};
In this example, I showed 3 different methods of accessing the underlying value of base.
As a result, the output is:
Further reading:
std::variant
std::get
std::get_if
std::visit

how to extract template derived class's method into non-template base class

I want using polymorphism in C++, I am try to extract method shows in all derived class into base class.
For example:
I have two class, HouseA and HouseB, they are template class.
And they are derived from base class BaseHouse.
class BaseHouse
{
public:
//other thing
private:
};
template <typename Type>
class HouseA : public BaseHouse
{
public:
HouseA(Type object_input) : object(object_input)
{
}
// other thing about HouseA
Type &getObject()
{
std::cout << "this is House A" << std::endl;
return object;
}
private:
Type object;
};
template <typename Type>
class HouseB : public BaseHouse
{
public:
HouseB(Type object_input) : object(object_input)
{
}
// other thing about HouseB
Type &getObject()
{
std::cout << "this is House B" << std::endl;
return object;
}
private:
Type object;
};
Bacause of polymorphism, we using base class's pointer to access derivated class object. When I need to call method defined in derivated class, I am always transfer base class pointer into derivated class pointer:
int main()
{
HouseA<int> house_a(5);
int x = house_a.getObject();
BaseHouse *base_ptr = &house_a;
// suppose after some complicate calculate calculation
// we only have the base class pointer can access derivated class object
HouseA<int> *ptr_a = (HouseA<int> *)base_ptr; //transfer base class pointer into derivated class pointer
ptr_a->getObject();
return 0;
}
But the derived class HouseA and HouseB both have the method getObject.
So I want to extract template derived class's method into non-template base class.
For some reason, we suppose that the base class BaseHouse can not be template class.
Is there any way I can do that?
Thanks in advance.
If the signature of the derived member depends on the template arguments (as your getObject does on Type) the member cannot be extracted into a non-template base. At least not without removing the ability of the member's signature to vary based on template arguments.
Maybe not exactly a classical Visitor, but...
Okay, the basic idea is we have to somehow capture and encapsulate templated processing into a single entity ready-to-use in a run-time polymorphic construct.
Let's start with a simple class hierarchy:
struct Consumer;
struct Base {
virtual void giveObject(Consumer const &) const = 0;
virtual ~Base() = default;
};
struct Derived1: Base {
Derived1(int x): x(x) {}
void giveObject(Consumer const &c) const override {
c(x);
}
private:
int x;
};
struct Derived2: Base {
Derived2(double y): y(y) {}
void giveObject(Consumer const &c) const override {
c(y);
}
private:
double y;
};
So far, it is very simple: the Base class has a pure virtual method that accepts an object of type Consumer and a concrete implementation of this method is expected to expose to Consumer the relevant part of the internal state of its particular implementor (which is a subtype of Base). In other words, we have taken that 'virtual template' idiom and hid it inside the Consumer. Ok, what could it possibly be?
First option, if you know in advance at compile-time (at source code-time, more exactly) what it could possibly do, i.e. there's only one algorithm of consumption per each object type, and the set of types is fixed, it is quite straightforward:
struct Consumer {
void consume(int x) const { std::cout << x << " is an int.\n"; }
void consume(double y) const { std::cout << y << " is a double.\n"; }
template<typename T> void consume(T t) const {
std::cout << "Default implementation called for an unknown type.\n";
}
};
etc.
More elaborate implementation would allow run-time construction of a templated entity. How is that even possible?
Alexandrescu in his "Modern C++ Design" uses typeid to store particular type handlers in a single data structure. In a brief, this could be something like:
struct Handler {
virtual ~Handler() = default; // now it's an empty polymorphic base
};
template<typename T> struct RealHandler: Handler {
RealHandler(std::function<void(T)> f): f(std::move(f)) {}
void handle(T x) {
f(x);
}
private:
std::function<void(T)> f;
};
#include <map>
#include <type_info>
#include <functional>
struct Consumer {
template<typename T> void consume(T t) const {
auto f{knownHandlers.find(typeid(t))};
if(f != knownHandlers.end()) {
RealHandler<T> const &rh{
dynamic_cast<RealHandler<T> const &>(*f->second)};
rh.handle(t);
}
else {
// default implementation for unregistered types here
}
}
template<typename T> Consumer &register(std::function<void(T)> f) {
knownHandlers[typeid(T)] = std::make_unique<RealHandler<T>>(std::move(f));
}
private:
std::map<std::type_info, std::unique_ptr<Handler>> knownHandlers;
};
Haven't actually tested it, as I don't like typeids and other RTTI much. What I have quickly tested is another solution that requires neither maps nor typeinfo to store handlers in a templated manner. Still it uses a small trick, like how can we possibly pass, keep and retrieve information of an arbitrary type with the same call.
struct Consumer {
Consumer() {}
template<typename T> void consume(T t) const {
auto f{setSlot<T>()};
if(f) f(t);
else {
// default implementation for an unset slot
std::cout << t / 2 << '\n';
}
}
template<typename T>
std::function<void(T)> &setSlot(
std::function<void(T)> f = std::function<void(T)>{}) const
{
static std::function<void(T)> slot;
if(f) { // setter
slot = std::move(f);
}
return slot;
}
};
Here, setSlot() is used to store a handler for a particular type: when called with a non-empty argument, it stores that argument; and then returns its currently kept value. With Consumer so defined, the class hierarchy from above works as:
int main() {
Consumer c;
c.setSlot<int>([](int x){ std::cout << x << " is an int!\n"; });
Base const &b1{Derived1{42}};
Base const &b2{Derived2{3.14}};
b1.giveObject(c);
b2.giveObject(c);
}
Output:
42 is an int!
1.57
In the first line we see a message printed by a custom int handler; in the second line, a default message is printed for the double type, as no custom handler for double was installed.
One obvious drawback of this implementation is that handlers are stored in static variables thus all Consumers share the same handlers for all types, so Consumer here is actually a monostate. At least, you can change implementations for types at run-time, unlike if you had fixed Consumers of the very first approach. The maps-of-typeids approach from above shouldn't have this drawback, in exchange for some performance cost.

Do I need to initiate parent class or just child class

I am new in programing and I am analyzing code with parent class fruit and child classes apple and pear. In this example there is pointer to parent class. After I extended this code I find out that using object I can access parent public members and all child members. Question is why do I need those pointers?
// are this pointer needed since I can use j.setWeight(11)
#include <iostream>
using namespace std;
class fruit {
private:
int weight;
public:
void setWeight(int x)
{
weight = x;
}
int getWeight()
{
return weight;
}
};
class apple : public fruit {
public:
void eat()
{
cout << "Now I am eating apple"
<< "=" << getWeight() << endl;
}
};
class pear : public fruit {
public:
void eat()
{
cout << "Now I am eating pear"
<< " = " << getWeight() << endl;
}
};
int main()
{
apple j;
pear k;
fruit* fruit1 = &j;
fruit* fruit2 = &k;
k.setWeight(5);
k.eat();
fruit1->setWeight(11);
apple apple;
apple.postaviTezinu(16);
apple.jelo();
return 0;
}
are this pointers needed since I can use j.setWeight(11) and results is same as
fruit1 -> setWeight(11) ... what s difference, thx
I suspect that the code you are looking at was written to demonstrate how pointers to base classes can be used with objects of derived classes. No, pointers are not necessary for the functionality of this learning exercise. In fact, that is probably the reason this functionality was chosen. Since you see how to accomplish the same thing without pointers, it should be easier for you to relate pointers to what you already know.
The key learning points I see in this exercise are
The same pointer type (fruit *) can point to objects of different types (apple or pear).
When using the pointer to the base class, you can access base class members.
When using the pointer to the base class, you cannot access derived class members. (Implied by omission; compare what is done with k to what is done with fruit1.)
You will need to move on to the more advanced lessons to learn when pointers are more useful than accessing objects directly (probably after eat() is turned into a virtual function). For now, just learn how the same task can be accomplished by different means.
(Sure, you could get that information here, but that code looks like it's part of a series. Continuing with that series might be the better way to learn.)
Since you're new to programming, learning polymorphism may be a bit advanced for you at this stage. To answer your question directly: No, you don't need pointers in your example code, and they are in no way helpful.
However, pointers to objects are often useful for:
Reducing unnecessary copying of objects
In the case of polymorphism (as in your example) pointers help in sections of your programme where you don't know which object type you're dealing with, or don't want to have to deal with them in different ways
Example:
#include <iostream>
#include <vector>
class A
{
public:
virtual void foo ()
{
std::cout << " I am A\n";
}
};
class B : public A
{
public:
virtual void foo ()
{
std::cout << " I am B\n";
}
};
void bar ( const std::vector <A*> & obj )
{
// Here it outputs the foo () function that is
// appropriate for the class
for ( unsigned int i = 0; i < obj . size (); ++i )
obj [i] -> foo ();
}
int main ()
{
A a1, a2, a3;
B b1, b2, b3;
// the below input style requires C++11,
// otherwise input them one-by-one
std::vector <A*> array {&a1, &b1, &a2, &a3, &b2, &b3};
bar ( array );
return 0;
}
The above array can store any A objects, including the inherited objects (it can't do this without pointers); and the bar function can still perform operations on the elements in the array without needing to know which object type they belong to within the inheritance tree (due to the virtual function). This is crucial for taking advantage of polymorphism, and saving on repetition of functions and code in general.

Call derived class non virtual member functions from base class pointer

We know that, derived class members functions can be accessed through a base class pointer in C++ , provided that these member functions have to be virtual. Is there a means to access derived class member functions which are NOT virtual or pure virtual from base class pointer.
i.e. I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this?
For example, if I design a factory design pattern,
class Vehicle {
public:
virtual void printVehicle() = 0;
static Vehicle* Create(VehicleType type);
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
void Some2WheelerONLYSpecificOPeration()
{
}
};
class ThreeWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am three wheeler" << endl;
}
void Some3WheelerONLYSpecificOPeration()
{
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am four wheeler" << endl;
}
void Some4WheelerONLYSpecificOPeration()
{
}
};
// Factory method to create objects of different types.
// Change is required only in this function to create a new object type
Vehicle* Vehicle::Create(VehicleType type) {
if (type == VT_TwoWheeler)
return new TwoWheeler();
else if (type == VT_ThreeWheeler)
return new ThreeWheeler();
else if (type == VT_FourWheeler)
return new FourWheeler();
else return NULL;
}
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->Some2WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL
basePtr = Vehicle::Create(VT_ThreeWheeler);
basePtr->Some3WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL
basePtr = Vehicle::Create(VT_FourWheeler);
basePtr->Some4WheelerONLYSpecificOPeration(); // //HOW TO ACHIEVE THIS CALL
}
I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this ?
You cannot call a non-virtual member function of the derived class with a pointer to the base class.
You'll need a pointer to the derived class. The simplest method is to use dynamic_cast to get a pointer to the derived class, check whether the cast was successful, then call the derived class member function using a derived class pointer.
A better method would be to provide a virtual member function in the base class and implement it in the derived class.
You can do what you want with dynamic_cast, but this will lead to disappointing results at a code review. Instead, I pitch you go the same route you did with printVehicle
class Vehicle
{
public:
// without a virtual destructor you are walking into
// a very bad bug. The wrong destructor may be called.
virtual ~Vehicle()
{
}
virtual void printVehicle() = 0;
// Specific stuff that all children must provide
virtual void doTypeSpecificStuff() = 0;
// this is actually a bit of a ideological weird. I'm not sure I can call
// it a flaw. By making this factory function a member of Vehicle, Vehicle
// must now know its children. If this is the case, the VehicleType enum
// should probably be a member of Vehicle, but personally I think this
// factory should be a totally free function.
static Vehicle* Create(VehicleType type);
};
class TwoWheeler: public Vehicle
{
public:
void printVehicle()
{
cout << "I am two wheeler" << endl;
}
void doTypeSpecificStuff()
{
cout << "Doing two wheeler stuff" << endl;
}
};
Leaving out the other two classes and Vehicle::Create to save space.
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->doTypeSpecificStuff(); //HOW TO ACHIEVE THIS CALL
// leaking memory here, so
delete basePtr;
// but also look into std::unique_ptr. Much better suited to this behaviour
}
In fact, let's act on on that final comment about std::unique_ptr right now. A unique_ptr manages your dynamic allocations for you so you don't have to clutter up your code with deletes and run the risk of missing one or deleteing too soon. The unique_ptr's pointer is valid for as long as the unique_ptr is in scope. If you can compile, the pointer is good unless you done something silly like never point it at anything or manually remove the pointer.
And while we're at it, let's eliminate my earlier concerns about vehicle::Create.
First we define a free function to replace Create and return a unique_ptr. Since I hate to have to have if (ptr != NULL) checks all through my code to make sure an object really was created, let's also make a big stink about it when we can't match the provided vehicle type with class by throwing an exception.
And rather than a chain of if-else ifs we'll use a somewhat more elegant switch statement.
std::unique_ptr<Vehicle> SmarterVehicleFactory(VehicleType type)
{
switch (type)
{
case VT_TwoWheeler:
return std::make_unique<TwoWheeler>();
case VT_ThreeWheeler:
return std::make_unique<ThreeWheeler>();
case VT_FourWheeler:
return std::make_unique<FourWheeler>();
default:
throw std::runtime_error("Invalid Vehicle type");
}
}
And then we'll use this new function
int main()
{
try
{
std::unique_ptr<Vehicle> basePtr = SmarterVehicleFactory(VT_TwoWheeler);
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_ThreeWheeler);
// unique_ptr freed the TwoWheeler for us.
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_FourWheeler);
basePtr->doTypeSpecificStuff();
// just for laughs we will ask for a FiveWheeler, which we have not yet
// fully implemented
basePtr = SmarterVehicleFactory(VT_FiveWheeler); // will throw exception
basePtr->doTypeSpecificStuff(); // will not be executed
}
catch (const std::exception & exc)
{
cerr << "Rats! Something bad happened: " << exc.what();
// basePtr will be unmodified and still pointing to a FourWheeler
}
} // basePtr will go out of scope here and clean up our memory for us.
The beauty of this approach is no class knows anything about any other class. You can put Vehicle in a header with the SmarterVehicleFactory prototype and the list of vehicle types and hide everything else. The user sees nothing. Everybody is kept in the dark.
Why is that good? Because now you can change any of the above classes, except the Vehicle interface class, without having any effect on any of the other classes. This makes your code easier to maintain and debug.
I'm trying to find the best way to use polymorphism without using inheritance, because I want to avoid virtual calls. I was looking for a way to improve what I currently have (with no avail) and I stumbled on this question. This is the best I can do so far:
template<class VehicleDetails>
class Vehicle {
VehicleDetails details;
public:
VehicleDetails& getDetails() {
return details;
}
const VehicleDetails& getDetails() const {
return details;
}
void printDetails() const {
details.printDetails();
}
}
class TwoWheeler {
public:
void printDetails() const {
cout << "I am two wheeler" << endl;
}
void specificTwoWheelerMethod() const {
cout << "I am specific functionality" << endl;
}
}
Then you use it as such:
Vehicle<TwoWheeler> vehicle;
vehicle.printDetails(); // prints "I am two wheeler"
Unfortunately this complicates things. Now every class/struct or function that takes a vehicle must be templated, unless you know the type of vehicle.
template<class VehicleDetails>
void doGeneralVehicleThings(const Vehicle<VehicleDetails>& vehicle) {
// ...
}
On the plus side when you do know the type you can access specific functionality via the getDetails() method without any casting or runtime overhead involved:
void doTwoWheelerThings(const Vehicle<TwoWheeler>& twoWheelerVehicle) {
twoWheelerVehicle.getDetails().specificTwoWheelerMethod(); // prints "I am specific functionality"
}

C++: Is it possible to have a template class which represents a conditional reference to a resource?

So sometimes I want an object to have a reference to a shared resource (let's say something of type A), or alternatively to have its own copy of an A.
Furthermore the object may find itself inserted and manipulated inside of containers (vector, list, set).
So far what I know is that I will want to use an implementation of unique_ptr if I have a polymorphic type that is to be in a container. So for a class HasAnA which owns an A to be able to be placed inside a container while still allowing its A's to also be B's (B in this case being a derived class of A), it must be like this:
class A {
virtual void a() { std::cout << "A" << endl; }
payloadA payload;
};
class B: public A {
void a() { std::cout << "A(B)" << endl; }
void b() { std::cout << "B" << endl; }
payloadB payload;
};
class HasAnA {
std::unique_ptr<A> my_A; // this allows me to build a std::vector<HasAnA>
OtherStuff my_other_stuff;
};
So this is great, what I'm looking for is how to implement a class I'll call RefersAnA. I'd like for a RefersAnA to either have ownership of its own A, OR refer to an A owned by something else.
Let's see.
class RefersAnA {
std::unique_ptr<A> my_A; // represents my own A: when I die, this A is dealloc'd
A* not_my_A; // someone else's A.
OtherStuff my_other_stuff;
RefersAnA () {
// in here is code that would skip initializing my_A if a valid A* was provided.
}
};
To me this isn't really as friendly as I would like. Could I make some sort of template class which abstracts the notion of "either being a unique ptr to the resource or a raw ptr to the resource"? It needs one bit to say which of the two it is, and one pointer.
Here's an idea:
struct RefersOrOwns
{
std::unique_ptr<T> own;
T & ref;
RefersOrOwns() : own(new T), ref(*own) { }
RefersOrOwns(T & t) : ref(t) { }
};
(Instead of own(new T) I would of course prefer own(make_unique<T>()), but that's a separate issue.)