how to assign base class object to a derived class object? - c++

Assuming I have a base class A and publicly derived class B, how should I assign A object to the A base class subobject of B?
class A {...};
class B : public A {...};
A a(..);
B b(..);
static_cast<A&>(b) = a; ???
Is that doable without writing assignement operator for B? Are there any potential problems with casting b to A&? Is that standard conformant?

Writing another answer to demonstrate why and how assign a base class object to a derived class object.
struct TimeMachineThing_Data {
..
..
};
class TimeMachineThing : private TimeMachineThing_Data
{
static std::stack<TimeMachineThing_Data> m_stateHistory;
void SaveState() {
m_stateHistory.push_back( static_cast<TimeMachineThing_Data&>(*this) );
}
void RestoreState() {
static_cast<TimeMachineThing_Data&>(*this) = m_stateHistory.front();
m_stateHistory.pop_front();
}
};
It's very useful and fully legitimate.
(Here is private inheritance, so only internally TimeMachineThing IS-A TimeMachinetime_Data)
Another one.
struct StructWithHundresField {
string title;
string author;
...
StructWithHundresField() {
...
}
};
class EasyResetClass : public StructWithHundresField {
int not_reset_this_attriute;
public:
void ResetToInitialStateAtAnyTime() {
static_cast<StructWithHundresField&>(*this) = StructWithHundresField();
}
}

That's a really bad idea. A is the base, B is a derived type. By casting B to an A, you are now using A's assignment operator, which isn't going to touch any of the extra derived data. At the end of that assignment, b is still considered to be of type B, even though it now contains an A. This is the opposite of the way inheritance is meant to be used.
Changing the line to b = reinterpret_cast<B&>(a); would be even worse. Then you would be pretending that a is a B when it's not, and you be reading invalid memory.
If you truly want to do this kind of assignment, you want:
class B : public A {
B& operator= (const A& a) { ... }
};
Then you can write a function to copy the information from the A, and somehow deal with the extra information in the derived type B, plus this would allow you to simply write:
b = a;

In C++ (as with other OOP languages) inheritance establish Is-A relationship.
That is, if B publicly inherit A, B = A.
You always can cast B instance to A reference without any worry.

Think for a minute about whether this is a good idea. Remember that if you have B subclassing A, then every B is an A but not every A is a B. For example, every dog is a mammal, but not every mammal is a dog. If you have a concrete B object, trying to set it to an A object isn't mathematically well-defined in most cases. Moreover, in the world of C++, because you B object is statically typed as a B, you can never assign it an object of type A in a way that will make it stop being a B. At best, you're going to overwrite just the A portion of the B object without changing any of the B-specific parts.

Slicing assignment is safe only, if your base class is in
standard layout: https://en.cppreference.com/w/cpp/types/is_standard_layout . Better even, if your derived class is also standard layout.
In particular, your base class must not contain virtual methods or a virtual destructor, and all non-static data members must have the same access control (like public or private). Your base class may have a base class itself, and it may have data members, that are objects of other classes, but all those classes, that you that way inherit into your base class, must also be standard layout.
If your base class is standard layout, then there is nothing wrong with a slicing assignment to it, as that is guaranteed to only touch the data members of the base class. All other cases are unsafe, though.

I would say you need an assignment operator that specifically copies an A object to a B object.
In general, it's a good idea to have one any way when copying objects of the same type. But objects of different types make it even more important.

static_cast<TimeMachineThing_Data&>(*this) = m_stateHistory.front(); can be rewritten without the cast as TimeMachineThing_Data & data = *this; data = m_stateHistory.front();.

Everyone should know assignment is a covariant binary operator and therefore cannot work correctly with virtual functions. This is true for most binary operators, but assignment is special because it is part of the C++ language.
If you are using OO, your objects should be uncopyable and always represented by pointers. Uniqueness of object identity is the heart of OO: objects are not values, they have a unique value (their address).
If you are playing with values you should be using the appropriate concepts: functional programming (FP). That's closures (applicative objects), switches, templates, variants, and other stuff.
Try to get a solid understanding of each before mixing them. In general FP subsumes OO so is the general methodology: OO is a special case that in special circumstances delivers safe dynamic dispatch. OO dispatch is linear which means it handles an unbounded set of subtypes but it also applies only to properties (functions with one variant argument, namely the object) and can't work for anything higher order (functions with more than one variant argument). Assignment is just another 2-ary function, hence, it can't be dispatched with virtual functions.

Related

Using base assignment operator to rewrite only part of struct [duplicate]

Assuming I have a base class A and publicly derived class B, how should I assign A object to the A base class subobject of B?
class A {...};
class B : public A {...};
A a(..);
B b(..);
static_cast<A&>(b) = a; ???
Is that doable without writing assignement operator for B? Are there any potential problems with casting b to A&? Is that standard conformant?
Writing another answer to demonstrate why and how assign a base class object to a derived class object.
struct TimeMachineThing_Data {
..
..
};
class TimeMachineThing : private TimeMachineThing_Data
{
static std::stack<TimeMachineThing_Data> m_stateHistory;
void SaveState() {
m_stateHistory.push_back( static_cast<TimeMachineThing_Data&>(*this) );
}
void RestoreState() {
static_cast<TimeMachineThing_Data&>(*this) = m_stateHistory.front();
m_stateHistory.pop_front();
}
};
It's very useful and fully legitimate.
(Here is private inheritance, so only internally TimeMachineThing IS-A TimeMachinetime_Data)
Another one.
struct StructWithHundresField {
string title;
string author;
...
StructWithHundresField() {
...
}
};
class EasyResetClass : public StructWithHundresField {
int not_reset_this_attriute;
public:
void ResetToInitialStateAtAnyTime() {
static_cast<StructWithHundresField&>(*this) = StructWithHundresField();
}
}
That's a really bad idea. A is the base, B is a derived type. By casting B to an A, you are now using A's assignment operator, which isn't going to touch any of the extra derived data. At the end of that assignment, b is still considered to be of type B, even though it now contains an A. This is the opposite of the way inheritance is meant to be used.
Changing the line to b = reinterpret_cast<B&>(a); would be even worse. Then you would be pretending that a is a B when it's not, and you be reading invalid memory.
If you truly want to do this kind of assignment, you want:
class B : public A {
B& operator= (const A& a) { ... }
};
Then you can write a function to copy the information from the A, and somehow deal with the extra information in the derived type B, plus this would allow you to simply write:
b = a;
In C++ (as with other OOP languages) inheritance establish Is-A relationship.
That is, if B publicly inherit A, B = A.
You always can cast B instance to A reference without any worry.
Think for a minute about whether this is a good idea. Remember that if you have B subclassing A, then every B is an A but not every A is a B. For example, every dog is a mammal, but not every mammal is a dog. If you have a concrete B object, trying to set it to an A object isn't mathematically well-defined in most cases. Moreover, in the world of C++, because you B object is statically typed as a B, you can never assign it an object of type A in a way that will make it stop being a B. At best, you're going to overwrite just the A portion of the B object without changing any of the B-specific parts.
Slicing assignment is safe only, if your base class is in
standard layout: https://en.cppreference.com/w/cpp/types/is_standard_layout . Better even, if your derived class is also standard layout.
In particular, your base class must not contain virtual methods or a virtual destructor, and all non-static data members must have the same access control (like public or private). Your base class may have a base class itself, and it may have data members, that are objects of other classes, but all those classes, that you that way inherit into your base class, must also be standard layout.
If your base class is standard layout, then there is nothing wrong with a slicing assignment to it, as that is guaranteed to only touch the data members of the base class. All other cases are unsafe, though.
I would say you need an assignment operator that specifically copies an A object to a B object.
In general, it's a good idea to have one any way when copying objects of the same type. But objects of different types make it even more important.
static_cast<TimeMachineThing_Data&>(*this) = m_stateHistory.front(); can be rewritten without the cast as TimeMachineThing_Data & data = *this; data = m_stateHistory.front();.
Everyone should know assignment is a covariant binary operator and therefore cannot work correctly with virtual functions. This is true for most binary operators, but assignment is special because it is part of the C++ language.
If you are using OO, your objects should be uncopyable and always represented by pointers. Uniqueness of object identity is the heart of OO: objects are not values, they have a unique value (their address).
If you are playing with values you should be using the appropriate concepts: functional programming (FP). That's closures (applicative objects), switches, templates, variants, and other stuff.
Try to get a solid understanding of each before mixing them. In general FP subsumes OO so is the general methodology: OO is a special case that in special circumstances delivers safe dynamic dispatch. OO dispatch is linear which means it handles an unbounded set of subtypes but it also applies only to properties (functions with one variant argument, namely the object) and can't work for anything higher order (functions with more than one variant argument). Assignment is just another 2-ary function, hence, it can't be dispatched with virtual functions.

C++ Constructor member initializer lists, Object Slicing

I have two classes
class A {
public:
virtual void doStuff() = 0;
};
class B : public A {
int x;
public:
virtual void doStuff() override { x = x*2;} //just example function
};
And another class that modify and use data from the previous
class Foo {
A a;
public:
Foo::Foo(A &a_) : a(a_) {}
};
now I create the objects, and passes to the Foo class
B b;
// edit b attributes,
Foo foo(b);
So at the argument list for the class constructor I know there is not the problem of object slicing, because is a reference, but what is the case at the moment of assign the variable a(a_)?
Since I don't know how much time the object b is going to live I need to make a secure copy. I have a lot of different derived classes from A, even derived from the derived.
Will there be a object slicing?,
Is there a solution to this, or I need to pass pointers (don't want this approach)?
This causes slicing. C++ built in polymorphism only works with pointer/reference semantics.
In fact:
class Foo {
A a;
that won't even compile, because A is not a concrete class.
To fix this, first make virtual ~A(){}; and then pass smart pointers to A around. Either unique or shared.
Failing that you can use your own bespoke polymorphism. The easiers way is to stuff a pImpl smart pointer as a private member of a class and implement copy/move semantics in the holding class. The pImpl can have a virtual interface, and the wrapping class just forwards the non-overridable part of the behaviour to it.
This technique can be extended with the small buffer optimization, or even bounded size instances, in order to avoid heap allocation.
All of this is harder than just using the built in C++ object model directly, but it can have payoff.
To see a famous example of this, examine std::function<Sig> which is a value type that behaves polymorphically.
There will be object slicing with what you currently have. You're calling the A copy-constructor in Foo's constructor, and there aren't virtual constructors.
Having a member variable of type A only reserves enough space within an instance of Foo for an instance of A. There is only dynamic binding with pointers and references (which are pointers under the hood), not with member variables.
You would have to use pointers to get around this or you could rethink whether you really need a set-up like this.
Yes, there is slicing.
There has to be slicing, because a B does not fit inside a A, but it is an A that you are storing inside the class Foo. The B part is "sliced off" to fit; hence the name.

C++: Incorporating inheritance, polymorphism, and factories

I'm currently trying to make a pair of classes which depend on each other. Essentially, objects of class B create objects of class A. However, I am also using an inheritance hierarchy, so all derivatives of class B must also be able to create derivatives of class A (each derivative of B corresponds to a derivative of A, so DerB1 makes DerA1 objects, and DerB2 makes DerA2 objects).
I'm having problems with my implementation, and it may be silly, but I would like to see if anyone knows what to do. My code is below (I HATE reading other people's code, so I tried to make it as easy to read as possible...only a few important bits, which I commented to explain)
class BaseB {} // Declare BaseB early to use in BaseA constructor
class BaseA
{
public:
BaseA(BaseB* b) {}; // Declare the BaseA constructor (callable by all B classes, which pass a pointer to themselves to the constructor so the A objects can keep track of their parent)
}
class DerA:public BaseA
{
DerA(BaseB* b):BaseA(b) {}; // Inherit the BaseA constructor, and use initialization list
}
class BaseB
{
public:
virtual BaseA createA() = 0; // Virtual function, representing method to create A objects
}
class DerB:public BaseB
{
BaseA createA() {
DerA* a = new DerA(this); // Definition of createA to make a new A object, specifically one of type DerA (Error1: No instance of constructor "DerA::DerA" matches the argument list)
return a; // Error2: Cannot return DerA for BaseA function
}
}
So, I have two main problems, one is practical (Error1, as I seem to simply be calling the function wrong, even if I try to typecast this), one is philosophical (Error 2, as I don't know how to implement the features I want. If anyone could point out why Error1 is occurring, that would be wonderful! Error2, however, requires some explanation.
I would like my user (programmer) to interact with all A objects the same way. They will have the same exact public functions, but each will have VERY different implementations of these functions. Some will be using different data types (and so will require function contracts), but many will have the same data types just with different algorithms that they use on them. I would like some piece of code to work exactly the same way if one class A derivative is used or another is. However, in my current implementation, it seems that I need to return a DerA object instead of a BaseA object (at the site of Error2). This means that I will need to write a segment of main code SPECIFICALLY for a DerA object, instead of any arbitrary A object. I would like something like:
BaseB b = new DerB(); // Declare which derivative of BaseB I want to use
BaseA a = b->createA(b); // Call the createA function in that derivative, which will automatically make a corresponding A object
This way, I can simply choose which type of B object I would like in the first line (by my choice of B constructor, or tag, or template, or something), and the rest of the code will look the same for any type of object B (as each has the same public member functions, even though each object will perform those functions differently).
Would I be better off using templates or some other method instead of inheritance? (I apologize for being intentionally vague, but I hope my class A/B example should mostly explain what I need).
Thank you for any help. I apologize for asking two questions in one post and for being long-winded, but I am trying to learn the best way to approach a rather large redesign of some software.
You have several syntactical issues to get the errors solved:
Add the ; after each class definitions.
The first line should be a forward declaration: class BaseB /*{} NO!!*/ ;
Add public: to make constructor of DerA accessible for DerB
BaseA createA() should return a value, not a pointner (according to signature): return *a;
There is another potential hidden slicing issue, as createA() returns a value, an not a pointer. This means that your returned object (here *a), would be copied but as a real BaseA object. So only the BaseA part of the object will be copied, not the derived part. This could lead to some unexpected surprises.
In order to avoid slicing, consider returning a pointer, changing the signature of createA() accordingly. The object pointed to would then keep the right type without loosing anything.
If you would later need to copy the object, you could use a static cast if you are absolutely sure of the real type of the object pointed to:
BaseA *pba = pdb->createA(); // get pointer returned
DerA da = *static_cast<DerA*>(pba); // static cast with pointer
If you would need to copy pointed BaseA objects without necessarily knwowing for sure their real type, you could implement a virtual clone function in DerA (e.g. prototype design pattern)

Why delete default copy and move ctor and assignment for base classes?

Why delete default copy and move ctor and assignment for base classes?
This is from Stroustrup's book (4-th edition c++).
Usually base classes are abstract so why would you worry about that at all,
when you can't even instantiate them.
The situation you are trying to avoid:
class A
{
};
class B : public A
{
};
class C : public A
{
int foo;
};
int main(int argc, char** argv)
{
A* c_ptr = new C();
A* b_ptr = new B();
*b_ptr = *c_ptr;//unless you explictly dissalow this, it can be done!
}
The answer is twofold; one is a matter of semantics and the other is a matter of practicality in C++.
Value types are interchangeable, a specific instance is not relevant, they should be copyable and assignable and act like regular types. Examples might include a specific date, the value of pi, a name, a colour.
Reference types represent an instance of a thing; the specific instance is relevant, it's not just a description of a thing. Semantically, it doesn't make sense to allow copying of these. Examples might include a person, a file, a thread.
Types that are polymorphic in C++ are reference types; they must be passed by reference (or pointer) in order to maintain the correct behaviour. In practice, copy constructors are not polymorphic; copying through a base reference can lead to slicing, and thus a change in behaviour, which is a very poor representation of a copy. It is quite popular to introduce a virtual method to allow "cloning" of the polymorphic type.
The question suggested base classes should be non-copyable and non-assignable, but in fact, it is only base classes that are intended to be used polymorphically where this applies.
There are occasions where a class is designed to be inherited from, but it is not designed to be used poymorphically; for example, boost::noncopyable and CRTP classes. In this case it also makes sense to prevent instances of classes derived from them to be held by reference to the base; usually by reducing the visibility of the constructor or destructor by making one or both of them protected or private. These classes do not require a virtual destructor.

Do you ever NOT want to use virtual inheritance of a mutual base class if you use multiple is-a inheritance?

If you have is-a inheritance relationships implemented with public inheritance, and have a diamond of inheritance you will have something like:
a stream class
input stream and output stream classes derived from stream
an input/output stream class derived from both
In this case, as used in the standard library (?), to the extent that iostream both is-a istream and is-a ostream, the istream isa-a stream and the ostream is-a stream, and furthermore they are the same stream, any functions in stream, which it makes sense to apply to iostream, should deal with the same underlying structure.
In C++, in order that the copies of stream in istream and ostream can be shared, it must be inherited by them virtually.
However, if you prefer, you can not inherit virtually and each time you refer to a member of the base class, specify which of the two copies (one in istream or one in ostream) you want (either by casting, or by using scope::blah).
My question is, [edit: is there any other case where] other than "This isn't really an is-a relationship, I used naughtily used public inheritance as a syntactic convenience when it wasn't conceptually valid" or "I never need to refer polymorphically to the base class from the most-derived class so the incredibly small overhead isn't worth it", there is any reason it WOULD be conceptually valid to inherit non-virtually and have two copies of the base class, one for each sister intermediate class?
Let's work into a simple example.
B B1 B2
| \ /
D D
On the left, we find a class derived from a single bass. Clearly reasonable in OO design for having an is-a relationship respecting the Liskov Substitution Principal.
On the right, both B1 and B2 are independent bases of D, and D can be accessed polymorphically using a B1* or B2* (or references). Hopefully we can accept that this is also a valid OO design (despite Sun deeming it too stressfully mind-bending for Java programmers ;-P). Then consider having some base functionality factored out of both B1 and B2 and made reusable: say they both operate on an arbitrary list of numbers to which they can reasonably grant direct/public access:
Container<int> Container<int>
\ /
B1 B2
\ /
D
If this isn't clicking yet, perhaps:
Container<int> Container<int>
\ /
Ages Heights
\ /
Population
It is reasonable to say that Ages is-a Container<int>, though it might add some convenient functionality like average, min, max, num_teenagers. Same for Heights, possibly sporting a different set of convenience functions. Clearly a Population can reasonably be substituted for an Ages or Heights collection (e.g. size_t num_adults(Ages&); if (num_adults(my_population)) ...).
The point here is that each supporting container isn't meant to have a 1:1 relationship with further-derived classes like Population; rather, it's meant to be exactly 1:1 with its immediately-derived class.
Again, whether composition or inheritance is used is an interface design decision, but it's not necessarily invalid to expose the containers publicly in this way. (If there's concern about maintaining Population invariants such as Ages::empty() == Heights::empty() the data-mutating functions of Container<int> might be made protected while const member functions were public.)
As you observe, Population does not have an unambiguous is-a relationship with Container<int> and code may need explicit disambiguation. That's appropriate. Of course, it's also possible and reasonable for Population to derive from Container<int> if it stores some other set of numbers, but that would be independent of the indirectly inherited containers.
My question is, other than "This isn't really an is-a relationship, I used naughtily used public inheritance as a syntactic convenience when it wasn't conceptually valid"
I see no issue with the is-a relationships or conceptual validity of the above, if you do please explain....
"I never need to refer polymorphically to the base class from the most-derived class so the incredibly small overhead isn't worth it"
I think it's clear I'm just doing data modelling based on natural object relationships, not some dubious optimisation. The supporting container class factored out of the bases is actually used and must be independent in each.
I would say it is more likely to cause havoc.
Let us ignore the case of stateful base class. It seems obvious that having two incoherent states is likely to cause confusion at least, and be error prone.
I would rather focus on the issue of identity. In C++, the identity of an object is determined by its address. This is the very reason why, apart from empty base classes, each object must at least have a size of one byte.
If you have the same base class multiple times in your hierarchy, then you could obtain two Base* that refer to the same object... and yet differ (point to a difference address).
Of course, you could pull your tricks and use a dynamic_cast<void*>(p) to get the "real" physical address of the whole object... but still.
The problem is one of identity; in the case of the iostream
hierarchy, the shared bases even have state, which gets set by
manipulators. If there were more than one instance of
basic_ios, you'ld have two copies of the state (formatting
flags, error state, even the streambuf), which would be
a disaster.
I can't really think of a case where you'ld want two copies of
a base class, but I imagine that they do exist.
An example
class Category
{
public:
virtual std::string CatName();
};
class OxygenBreath : public Category
{
public:
virtual void Breath() = 0;
std::string CatName(){ return "OxygenBreath";}
};
class LandWalk : public Category
{
public:
virtual void Walk() = 0;
std::string CatName(){ return "LandWalk";}
};
class Human : public OxygenBreath, public LandWalk
{};
There might be cases where this is useful. Say a touchscreen class deriving from display_device and input_device? Now suppose each base the common base class has an estimated_power_consumption field, wouldn't it be useful to avoid virtual inheritance?
struct managed
{
report(std::string what);
private:
manager_type manager;
protected:
managed(manager_type);
};
struct human : managed
{
human() : managed(god) {}
};
struct robot : managed
{
robot(manager_type owner) : managed(owner) {}
};
struct employee : managed
{
employee(manager_type boss) : managed(boss) {}
};
struct human_employee : human, employee
{
human_employee(manager_type boss) : employee(boss) {}
};
struct robot_employee : robot, employee
{
robot_employee(manager_type owner) : robot(owner), employee(owner) {}
};
Now, consider:
void do_some_duty(const employee& e)
{
e.do_some_tasks();
e.report("done");
}
void face_disaster(const human& h)
{
h.report("Oh my!");
}
void commit_suicide(const managed& m)
{
m.report("I want to suicide");
}
and as a human employee, the one you report to is different if you're working of not:
human_employee h;
if (h.at_work()) commit_suicide(static_cast<const employee&>(h));
else commit_suicide(static_cast<const human&>(h));
I would even consider using such a design if I really needed to. You can imagine in lieu of managed some class which would store a reference to a global manager object for eg. garbage collection. In this case it really makes sense to have distinct base classes for base objects.
Theoretically speaking, I can imagine a reason to inherit "sisters" B and C from common A non-virtually privately , then inherit publicaly some "compound class" D from A and B.
It is, of course, not an is_a relationshipn between most derived (D) and most base class (A) as private inheritance does not exhibit is_a relationship to users and furher descendants.
However, if B and C sister classes are not designed especially for this case (i.e for diamond inheritance), they may be publicaly inherited from A.
The effect is almost the same as for private inheritance: we can't access A members from D ([edited:at least without explicit casting to sisters; ] any attempt will be ambiguous).
So one may treat public nonvirtual inheritance as a replacement for private nonvirtual inheritance.
But I would never do such tricks.
Iheritance itself is a useful metaphor but not a basement of the universe, and using it subtle features leads to unnecessary complicated design.
IMO, if a replacement of simple(nonvirtual) inheritance with virtual one is (conceptually) unacceptable, there is almost surely a design flaw.
So I would answer "no" (despite of my "theretically speaking..." construction :)