C++ Syntactical anomaly for instantiation of a derived class - c++

I am working with a GitHub library and ran across a derived class instantiation that perplexes me. In abbreviated form,
class A
{
public:
A() {}
int AFunc(void) { return(1); }
};
class B : public A
{
public:
B(void) : A() {}
int BFunc(void) { return(2); }
};
Within an include file, the class is instantiated as follows:
A &tObject = *(new B());
Sample code then refers to 'tObject' as global variable calling methods from class A and/or B.
For example:
tObject.AFunc();
tObject.BFunc();
So here's the question, is that instantiation legal?
The compiler is only fussing on the call to a service class's method, saying that class A has no such member. That error makes sense to me and I've narrowed the issue to the above explanation.
While I do not have broad compiler experience, I have been programming in C++ for many years. I've never seen such a construct.
Would someone kindly explain how an object declared, in my example, as 'class A' can access methods from the derived class B?
In my experience, I've always declared the derived class as a pointer and then accessed methods from the base or derived class using the '->' construct. Oftentimes, I've stored the derived class as a pointer to the base and then performed a cast to convert when or if I needed access to the derived class's methods.
An insight is highly appreciated.

It cannot. The compiler is right to complain, there is no way this is valid. Remember that C++ is a static language, which means that the compiler will try to find a function named BFunc in A, which it cannot, as there is no such function.
This might be a compiler extension of some sort, but anyways, this isn't legal standard C++. Most probably, the author wanted to make BFunc a virtual method in A, which would have made the access legal.
Would someone kindly explain how an object declared, in my example, as 'class A' can access methods from the derived class B?
As explained, this cannot be.
I've always declared the derived class as a pointer and then accessed methods from the base or derived class using the '->' construct.
You can also do this with references, not just with pointers. Although this is done less often than pointers, so this might explain why you haven't encountered this yet.
Oftentimes, I've stored the derived class as a pointer to the base and then performed a cast to convert when or if I needed access to the derived class's methods.
Exactly, this is the correct way to access the derived class members. As then the compiler will know the type of the object and can actually find BFunc and call it. Now, if the type is not really a B, then you have undefined behavior, but yes, this is what one should do.
Also, please get your terminology right:
the class is instantiated as follows
If there are no templates involved, then there is no instantiation happening. The only thing you are doing here is declaring or more specifically defining a variable named tObject.

// The declaration of the reference as a reference to the base class is not a problem, and is actually performed in some STL implementations.
class A
{
};
class B : public A
{
public:
void f1() {}
};
int main()
{
A * a = new B; // You know its OK using pointers
A & a2 = *(new B); // Also OK, a2 is a reference for a place in memory which is-a-kind-of A
// a2.f1(); // Will not compile - compiler only knows for sure its of type A
((B&) a2).f1(); // This will work. There is really a B there
return 0;
}

Related

Declaring an extern variable as base and derived class pointers

Say we have a situation like this:
base.h:
class Base { };
derived.h:
#include "base.h"
class Derived : public Base { };
extern Derived *variable;
derived.cpp:
#include "derived.h"
Derived *variable;
Is it correct to declare variable as a pointer to Base in elsewhere.cpp?
class Base;
extern Base *variable;
The C++Builder linker doesn't complain and everything seems to work. Is this safe and correct according to the standard, or should every declaration of variablebe of the same type?
Here's a few ways this can go wrong (aside from being undefined behavior, which means that you shouldn't even rely on one of those happening):
The compiler might make the type part of the mangling of the variable. Apparently C++Builder doesn't, but I'm pretty sure MSVC does. If it does, you get linker errors.
Suppose at some point Derived is changed to
class Derived : public Something, public Base {};
where Something isn't empty, then in most ABIs, a Derived* changes its value when it's cast to a Base*. However, the aliasing of the global variable bypasses this adjustment, leaving you with a Base* that doesn't point to a Base.
The compiler might actually detect your ODR violation through some other means and just error out.
What happens if you assign an object of type OtherDerived (which also derives from Base, but not Derived) to your variable? The parts of the program that see it as a Derived* expect it to point to a Derived, but it really points to a OtherDerived. You can see the most fascinating effects in such code. You could set it up so that calling virtual function foo calls the Derived version while foo2 calls the OtherDerived version. The possibilities are endless.
It's not OK. If the name variable is supposed to refere to the same entity (which it is, since it's extern), then it must have the same type. Otherwise, you'll be violating ODR (One Definition Rule).
Of course it's not fine.
It creates an ambiguity in some cases:
// Example Function:
void do_stuff(Base* b);
// Code
do_stuff(variable); // You could mean Derived* or Base*.
// You would write the same thing, but mean
// 2 different things.

c++ base class contain instance of a derived class

I was wondering if someone could explain to me how I might be able to implement something similar to this:
namespace advanced_cpp_oop
{
class A
{
B b;
};
class B : public A
{
};
}
int main()
{
}
Where an instance of a base class can contain an instance of a derived class? When the above code is compiled the following error is generated:
g++ advanced_cpp_oop.cpp
advanced_cpp_oop.cpp:8:5: error: ‘B’ does not name a type
The (almost) equivalent Java code which does compile is:
public class AdvancedCppOop
{
public static void main(String[] args)
{
A a;
}
}
class A
{
B b;
}
class B extends A
{
}
Thanks
You need to add a pointer and a forward declaration:
namespace advanced_cpp_oop
{
class B;
class A
{
B* b;
};
class B : public A
{
};
}
In your C++ code, you are creating an instance of your class B inside class A, which is not possible since the compiler does not yet know anything (especially not the size) of class B.
With the code from my answer, you need to dynamically allocate an instance of class B and assign it to the b pointer somewhere else in your code.
On a side note, from design perspective, this does not really make sense since a parent class should not depend on a sub class.
You have to do it with some type of pointer, such as unique_ptr, and a forward declaration:
class B;
class A
{
std::unique_ptr<B> b;
};
class B : public A
{
};
This is silly though and you should probably rethink your design.
There is one very important difference between C++ and Java. C++ is a language with value semantics, while Java is a language with reference semantics. When in Java you create a variable of anything other than a primitive type, you are not creating an object of that type, but a reference to such an object. On the contrary, in C++ the same construct refers to an actual object.
If you keep this in mind, it is simple to understand why the following cannot possibly work:
class Base {
Derived d;
};
class Derived : Base {};
The first definition in C++ means that the object Base contains internally (not by reference) an object of type Derived. At the same time, Derived contains by means of inheritance a subobject of type Base.
That means that Derived contains a Base that contains a Derived containing a Base...
What would be the size of Base or Derived?
In a language with reference semantics, or in C++ if you use pointers, that is not a problem. The Base object contains a reference/pointer to Derived. Derived contains a Base subobject by means of inheritance. The size of Base is well known: all the other fields plus the size of a reference/pointer. The size of Derived is whatever the size of Base is plus any extra members that are added.
Andreas beat me to the correct answer, but I'll just add that the Java code works only because Java objects are implicitly held by pointers (hence the B b = new B(...); statements sprinkled throughout Java code) even if it doesn't look like it. Your original C++ code doesn't work (even with a forward declaration of class B added) because the compiler doesn't know how big a B object is, and thus doesn't know how big an A object that contains it will be. On the other hand, all pointers have the same size (regardless of pointed-to type), so the compiler has no such problems when you replace a B object with a pointer to a B object in class A.

Why am I getting the error "A is an inaccessible base of B" when using dynamic_cast and templates?

Why is the call to f not resolving to the first function overload? I get the error:
source.cpp: In function 'int main()':
source.cpp:12:31: error: 'A' is an inaccessible base of 'B'
class A {}; class B : A {};
void f(const A &) { std::cout << "const A &"; }
template <typename T> void f(T) { std::cout << "Generic"; }
int main() {
B b;
f(dynamic_cast<const A &>(b));
}
Note that if I take out the dynamic_cast the code will work yet the second f is called (it prints "Generic"). But what I'm trying to do is to get the first call. I figured a dynamic_cast would work, but for some reason it causes problems. What am I doing wrong here?
The default class inheritance is private (class B : A {}; defaults to class B : private A {};).
So you can't handle b through type A.
EDIT:
Like Rob said :), the way to fix it is by using public inheritance:
class B : public A {};
EDIT:
The relationship between a publicly derived class and its base class is "is a", meaning that it is a specialization of a more generic type, and as such, it implements the behavior of that generic class and possibly more.
The relationship between a privately derived class and its base class is "implemented in terms of". It prevents objects from being considered extensions of the base class. A good example of its use is boost::noncopyable that prevents objects of a privately derived class from being copied.
http://www.boost.org/doc/libs/1_52_0/libs/utility/utility.htm#Class_noncopyable
In the hypothetical case that the requirements include private inheritance and at some point a function is created that wants to reference the object as its base, a public method returning a casted to base class pointer this will do it much like a traditional get() accesses a private data member maintaining the original purpose.
public:
A *getBase() { return static_cast<A *>(this); }
And then accessed like this:
f(b.getBase());
A is a private base of B, so there are very few places where an object of type B can be treated as an A&. If you change the inheritance to public the cast will work, and select the non-template version of f. But dynamic_cast is overkill; every object of type B is an object of type A, so you can use static_cast to disambiguate the call.
There's nothing special about dynamic_cast when it comes to upcasts. dynamic_cast is equivalent to static_cast in such cases. It is performed at compile-time if the base exists, is unambiguous and is accessible. It fails to compile otherwise.
This is exactly what happens in your case. The base is inaccessible (as the compiler told you already) so the cast fails to compile.
Without the cast the first function is excluded from the overload resolution candidate list (since the base is inaccessible), and the second one wins.
In fact, you don't really need any cast to perform legal upcasts in overwhelming majority of cases. As for illegal upcasts, no C++ cast will help you with that (the only cast that can "break through" private inheritance is C-style cast.)
It will fail because of the private inheritance, as mentioned, and because b is passed as an object. dynamic_cast will only work for pointers and references.
See: http://www.cplusplus.com/doc/tutorial/typecasting/

Problem with declaring Objects in C++

I have a simple code below:
class B;
class A{
B b;
};
class B{
public:
B(){
}
};
In class A's definition, I have a B-typed property. Using MS Visual Studio to compile, I've got the following error:
error C2079: 'A::b' uses undefined class 'B'
Due to some reasons, I can't put class B's definition before class A's one. Any idea?
The compiler is already telling you what's wrong : A has a member data b which is of an undefined type. Your forward declaration:
class B;
is just that : a declaration, not a definition. Since class A contains an instance of B directly (not just a pointer to B), the compiler needs to know the exact size of B : it needs its definition, not just a declaration, i.e. a promise that B will exist at some point.
The simplest thing to do here would be to reorder things this way:
class B{
public:
B(){
}
};
class A{
B b;
};
Edit : see also this question for the difference between declaration and definition.
Further edit : an alternative would be to change your member data to a pointer or a reference.
Do note that this isn't a trivial syntax change: it has implications on the life-cycle of your objects since the object pointed by A::b may then survive the destruction of A.
If what you want is composition (B is a part of A and dies with A), using a pointer will make your life harder with little benefits.
More edits(!) : just realized I misread the end of your question; what are the reasons preventing you from declaring B before A ?
If they cannot be worked around, you may have to go the pointer route. These reasons might be a sign that your objects are too tightly coupled though ! (perhaps B needs to be an inner class of A ? Or simply be merged into a single object ?)
class A;
class B {
A * getA();
};
class A {
B b;
};
This is the typical way to solve this. You must have B's definition in order to have a B b; member.
You need a forward declaration in order to declare a reference/pointer to B, you need the full definition in order to do anything else with B (such as defining a variable, calling a member function and so on)
You can do what you wish if you change the reference to b into a pointer to B.
class A{
B* bPtr;
};
class B{
public:
B(){
}
};
In principle, you don't need an explicit declaration - that is, a forward declaration is all that is needed - when you don't need the actual size of the class, or access to the types and member functions inside the class.
In your original example, you are making a direct reference to B. As a result, the compiler needs to know everything about B, thus requiring an explicit declaration instead of a forward one.
By having your A class declaration using a pointer to B, then you can get away with a forward declaration.
edit
Some links might explain the concept for you:
http://www.goingware.com/tips/parameters/notrequired.html
http://www-subatech.in2p3.fr/~photons/subatech/soft/carnac/CPP-INC-1.shtml
http://www.codeguru.com/forum/showthread.php?t=358333 (see post #2)
http://en.wikipedia.org/wiki/Forward_declaration
C++ has the concept of an "incomplete" class and it is something you need to know.
Using an incomplete class allows you, in many situations, to use a class just knowing it is one, without knowing what is in it.
This enables the class detail to change later without requiring a recompile, thus it is a far weaker dependency in the coupling model.
You need a complete class to:
Have an instance of one.
Derive from it
Call any method on it.
delete a pointer to it.
You only need an incomplete class to:
Hold a pointer or reference to it.
Pass a pointer or reference to a function that takes a pointer or reference. (This can be a function that deletes the pointer, as long as it is fully defined at that point).
I think you only need an incomplete class to declare a function that returns one, and possibly to declare a function that takes one as a parameter, but at the time you define or call the function it needs to be complete, even if you don't use the return value.

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!!!
}