C++ Inheritance "Ignored" - c++

I have this block of code:
struct Road_Primitive {
public:
Road_GPU_Point A;
Road_GPU_Point B;
Road_GPU_Point C;
};
struct Road_Primitive_4P : public Road_Primitive {
Road_GPU_Point D;
};
struct Road_Primitive_3P : public Road_Primitive{
};
And in one of my classes I have a Road_Primitive*, which is initialized with either new Road_Primitive_4P or new Road_Primitive_3P, depending on other factors.
However, this section of code gives me an "class Road_Primitive has no member D":
Road_Primitive* pmtv_Prospect = new Road_Primitive_4P;
pmtv_Prospect->D.X = pch_Rightmost->GPU_Primitive->B.X;
However, if I declare Road_Primitve with protected members, the error turns into something like: "Member B is inaccesible"
Any suggestions?

Well, class Road_Primitive hasn't any member D. Every expression is interpreted in light of the declared types of all its sub-expressions, as evaluated by the compiler. The fact that pmtv_Prospect currently points to a Road_Primitive_4P at some point during the execution doesn't factor in -- if you access that Road_Primitive_4P via a Road_Primitive * then you have access only to those members declared by class Road_Primitive.
If you want to be able to access Road_Primitive_4P.D, then you must do so via a value of (declared) type Road_Primitive_4P. Thus, you could write
Road_Primitive_4P* pmtv_Prospect = new Road_Primitive_4P;
pmtv_Prospect->D.X = pch_Rightmost->GPU_Primitive->B.X;
Of course, in that case you cannot assign pmtv_Prospect to point to a Road_Primitive_3P, but that's really the whole point. If you could make it point to a Road_Primitive_3P, which has no member D, then it would not be safe to access the referent's D.

struct Road_Primitive, does not, in fact, have a member called D. Although you're allocating a Road_Primitive_4P, you're storing it in a pointer to type Road_Primitive, so when you access (pmtv_Prospect) you only have access to the fields in Road_Primitive.
Usually when you store instances of child classes as parent classes, you want polymorphism, and virtual methods, or else some other means of telling which of those child classes the pointer really points to.
In order to use "dynamic_cast" as Gaurav suggested, your structs or classes need to have at least one virtual method. Starting with a destructor is probably a good idea:
struct Road_Primitive {
public:
virtual ~Road_Primitive() {};
// etc.
And one in each child class:
struct Road_Primitive_4P: public Road_Primitive {
public:
virtual ~Road_Primitive_4P() {};
Then if you have a Road_Primitive pointer and want to access members of it that are only accessible in Road_Primitive_4P you can use dynamic_cast:
Road_Primitive_4P* temp = dynamic_cast<Road_Primitive_4P*>(pmtv_Prospect);
if (temp) // then do something with temp->D
dynamic_cast() will return 0 if the object doesn't match the type you're trying to cast to.
Also bear in mind that this style of polymorphism is generally considered bad style because it tends to centralize behaviors that are specific to the different types. Using virtual methods is usually preferable because the behavior specific to each type is stored in the definition of that type.

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.

Can I delete a union component without checking whether it stores that object?

I mean the following. I have a few classes which inherit the same base class. Union consists of pointers of these classes:
#include "stdio.h"
class A {
public:
A() { printf("A\n"); }
virtual ~A() { printf("~A\n"); }
};
class B : public A {
public:
B() { printf("B\n"); }
virtual ~B() { printf("~B\n"); }
};
class C : public A {
public:
C() { printf("C\n"); }
virtual ~C() { printf("~C\n"); }
};
int main() {
union {
B* b;
C* c;
} choice;
choice.b = new B();
delete choice.c; //We have B object, but deleting C
return 0;
}
It seems to work, but I'm not sure if it isn't implementation-specific behaviour. Can I use such weird deleting method or should I remember a type of stored object and delete it respectively?
P.S. I use C++11 and want it works on both GCC and Visual C++ (2012 and higher). In a real project I have more complex class hierarchy but all of them are successors (directly or indirectly) of the same abstract base class
This is a double dose of undefined behavior. First, you can't delete a B through a pointer to C. §5.3.5 [expr.delete]/p3:
In the first alternative (delete object), if the static type of the
object to be deleted is different from its dynamic type, the static
type shall be a base class of the dynamic type of the object to be
deleted and the static type shall have a virtual destructor or the
behavior is undefined. In the second alternative (delete array) if the
dynamic type of the object to be deleted differs from its static type,
the behavior is undefined.
Second, accessing the inactive member of a union is also undefined behavior in C++.
There's no need to use an union here anyway. B and C share the same base class, so you can just store the pointer in an A *.
You shouldn't. You are only allowed to read from the union member you last wrote into and you're only allowed to delete an object through a pointer to a base class (if it has a virtual destructor). It may seem to work now, but you may find it to break randomly in the future, usually due to an aggressive optimizer.
Why don't you store a pointer to A instead of the union?
As it has been said in other answer, this is not proper C++.
My impression is that you want to keep an union of pointers because in certain circumstances you need an instance of a (sub)class of B, and in another an instance of C, with the issue of B and C having not quite the same interface. Perhaps you store several of these in a container, or simply you don't know until runtime which instance will be used.
So you may keep your code as it was, with perhaps a type tag somewhere indicating which instance has been created, and then use a switch each time you need to determine the correct code to run, or you could leverage your classes to actually invoke the proper function at run time, by including in the common base class of B and C(1) a virtual method, and overload this method in B and C with the proper branch of the switch, then replace the union with a simple pointer to the base class.
(1) that base class doesn't have to be A: if you don't want to clutter your class tree, just make a different class having the minimal interface needed there, and thanks to C++ multiple inheritance, have B and C inherit from it as well. Don't forget the virtual destructor!
For me this case looks legit and there is no undefined behaviour.
He is using type-punning and it is legit because it B* b and C* c in union members is a pointers and could be converted to char array.
Both B and C have virtual destructor because of base class (not because base is a same! but because base have virtual destructor).
12.4.9 If a class has a base class with a virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.
While destructor call, (because it is virtual) exact function address will be picked up from choice variable and proper destructor sequence will be called. So there is no ANY undefined behaviour at all.

Why does the size of a derived class include private members from the base class?

I have the following code:
class A {
private:
int i;
};
class B : public A {
private:
int j;
};
When I check sizeof(B), it appears to be sizeof(base) + sizeof(derived). However, my understanding of inheritance is that the private members of a base class are not inherited. Why then are they included in the result of sizeof(B)?
all member variables are inherited. the private protected public modifiers only alter who has access to those variables
You misunderstand what private does. In your code snippet it simply prevents non-members and non-friends of A from accessing i. It's just an access-control modifier. Instances of B will have data members of A, even though B won't have (direct) access to it.
An analogy that shows that this does in fact make sense:
class Human
{
protected:
void UseCognitivePowers() { brain.Process(); }
private:
Brain brain;
// ...
};
class StackOverflowUserInSilico : public Human
{
private:
void AnswerStackOverflowQuestion(int questionId)
{
// ...
// magic occurs here
// ...
UseCognitivePowers();
}
};
Even though brain is private in the Human class, StackOverflowUserInSilico will have a Brain since StackOverflowUserInSilico derives from Human. This is needed, otherwise the UseCognitivePowers() function won't work even though StackOverflowUserInSilico inherits the method from Human.
Of course whether subclasses of Human will actually take advantage of the UseCognitivePowers() method afforded to them by the Human class is a totally different matter.
You either misunderstand sizeof or your misunderstand the layout (in memory) of C++ objects.
For performance reason (to avoid the cost of indirection), compilers will often implement Derivation using Composition:
// A
+---+
| i |
+---+
// B
+---+---+
| A | j |
+---+---+
Note that if private, B cannot peek in A even though it contains it.
The sizeof operator will then return the size of B, including the necessary padding (for alignment correction) if any.
If you want to learn more, I heartily recommend Inside the C++ Object Model by Stanley A. Lippman. While compiler dependent, many compilers do in fact use the same basic principles.
It is inherited - the derived class object will contain it, but it can't be accessed by member functions of the derived class.
This has already been answered in a few other answers: access specifiers restrict access, but the member attributes of the class are still inherited.
I just wanted to provide a rationale, as I usually learn better when I see the reasons for that. Basically, when you inherit from an type, the derived type contains a subobject of the base type, as small or large as the base might be. The reason for needing all of the member variables is that the derived object is a base object, and base level member functions can be called on it. Even if the derived type cannot access the private member attribute, the base methods that can be called on that object might still need to access it, so the members must be there:
class base {
int x;
public:
base() : x(0) {}
// ...
void printout() {
std::cout << x << std::endl;
}
};
class derived : public base {
// ... assume that derived does not hide `printout`
};
int main() {
derived d;
d.printout(); // this requires access to d.base::x
}
This is only a simple example, and there are a few things that you can say here to argue that in some cases x can be made unneeded (we are overriding/hiding printout in the derived object...) but the language still allows you to access a hidden/overridden member method by qualifying, so d.base::printout() would still access printout at the base level, and that in turns requires x.
Access specifiers (public/private/protected) don't affect inherited "object size" in anyway.
i dont know what language this is, but when you inherit the original object still exists. that is why you can still call base.method()

how to assign base class object to a derived class object?

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++ allocate objects on heap of base class with protected constructors via inheritance

I have a class with protected constructor:
class B {
protected:
B(){};
};
Now I derive from it and define two static functions and I manage to actually create objects of the class B, but not on the heap:
class A : public B {
public:
static B createOnStack() {return B();}
//static B* createOnHeap() {return new B;} //Compile time Error on VS2010
};
B b = A::createOnStack(); //This works on VS2010!
The question is: 1) Is VS2010 wrong in allowing the first case? 2) Is it possible to create objects of B without modifying B in any way (no friendship and no extra functions).
I am asking, because it is possible to make something similar when dealing with instances of B and its member functions, see:
http://accu.org/index.php/journals/296
Thank you in advance for any suggestion!
Kind regards
Yes, this code is non-compliant. This is related to special rules for protected member access (C++03 draft, 11.5/1):
When a friend or a member function of a derived class references a protected nonstatic member function or
protected nonstatic data member of a base class, an access check applies in addition to those described earlier in clause 11.10). Except when forming a pointer to member (5.3.1), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class) (5.2.5).
When you use B() or new B(), you're effectively using the constructor through a pointer to the base class.
You can create an object of type A (I assume that A is as posted - no additional members/non-static functions) and use it instead. If you're creating it on stack, everything should work fine, unless you're trying to assign other objects of type B to it. If you're creating it on heap, everything is fine as long as B's destructor is virtual. If B's destructor is not virtual, and you're returning new A() as a B*, then deleting the pointer is technically undefined behavior (5.3.5/3:
In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
However you'll probably find it working fine in practice, so you can rely on the actual behavior if there is no other workaround (i.e. use it as a last resort).
There is a common misunderstanding on what protected actually means. It means that the derived class can access that particular member on itself not on other objects. The compiler should have rejected both functions as in both cases it is accessing the constructor of an object that is not of the derived type.
Another example, easier to discuss for its correctness would be:
struct base {
protected:
int x;
};
struct derived : base{
static void modify( base& b ) {
b.x = 5; // error
}
};
The commented line is an error as it is trying to modify an object of type base, not necessarily a derived object. If the language allowed that code to compile, then you would be able to modify an object of type base or even objects of types derived1, derived2... effectively breaking access rules.
struct derived2 : base {};
int main() {
base b;
derived2 d;
derived::modify( b ); // modifying a base!!!
derived::modify( d ); // modifying a derived2!!!
}