C++ class compilation - c++

Why does the following compile ??
class A{
A(){
A* a = new A() ;
}
} ;
Shouldn't it fail for the same reason something like fails ?
class A{
A obj;
} ;

class A{
A obj;
} ;
is a recursive bomb because A's size is based on A. Obviously that can't be allowed. A doesn't know how big A is and never will. This is easy to catch at compile time.
class A{
A(){
A* a = new A() ;
}
} ;
Is still a recursive bomb, but it will blow up at run time, making it a logical error and not a syntax error. The compiler may emit a warning.
The secret here is that functions defined in a class are, through the magic of inlined functions ([dcl.fct.spec] point 3, but is seems to be point 4 under [dcl.inline] in more recent drafts of the standard), and compiled after the class is defined when it is used in other code (or not at all, as M.M points out below, if the function is never used).
Since the function will be moved outside of the class definition before it is compiled, the size of A is known at the time the function is compiled so it can be constructed safely.
As for A* a, that's just a pointer. The size is baked right in and has no special requirements.

The declaration
class A{
A obj;
} ;
is illegal because you declare an infinite storage this way. Note, that
containing a static field of own class or non-static of base class is legal though.
class A {
public:
static A a;
};
A A::a = A();
class B : A {
A obj;
}
Things like
class A{
A(){
A* a = new A();
}
};
are possible, whatever is declared inside method is a different storage. It is legal by the language rules but semantically it is wrong, a call to such constructor would cause an infinite recursion.

Related

C++ function overload for classes

I have 3 classes
class A {
//...
}
class B : public A {
//...
}
And a class C:
#include "A.h"
#include "B.h"
class C
{
void method(A anObjOfA);
void method(B anObjOfB);
}
Now if I do
B* ptr = new B();
A* ptrToB = ptr;
c.method(*ptrToB);
It calls the method for Objects of type A, not the inherited actual type B.. How can I make sure the right function for the object deepest in the inheritence-tree is called, without actually knowing it's type at compile-time?
PS: I'm sure this is a noob question, for the life of me I can't find any results on this here, as everyone is busy understanding the "virtual" keyword, which is perfectly clear to me but is not the issue here.
Because resolving a function overload is done at compile-time. When you call the function it only sees the A part of the pointer, even though it could point to a B.
Perhaps what you want is the following:
class A
{
public:
virtual void DoWorkInC()
{
cout << "A's work";
}
virtual ~A() {}
};
class B : public A
{
public:
virtual void DoWorkInC()
{
cout << "B's work";
}
};
class C
{
void method(A& a)
{
a.DoWorkInC();
}
}
Let your class A, B have virtual function implemented in their respectivbe classes:
class A {
//...
public:
virtual void doTask();
};
class B : public A {
//...
public:
void doTask();
};
Ket A::doTask() and B::doTask() do respective tasks in object specific way, i.e. A::doTask() to do tasks with visibility of the object set as an A object, and B::doTask() to do tasks with visibility of the object set as an B object.
Now, let the call be like this:
B* ptr = new B();
A* ptrToB = ptr;
c.method(ptrToB); // pointer is passed
Within C::method(A *ptr), it may be something like:
void C::method(A * ptr) {
ptr->doTask(); this would actuall call A::doTask() or B::doTask() as dynamically binded
}
thanks to #texasbruce I found the answer, RTTI
The code will look like this:
A* someAOrBPtr = ...
...
B* testBPtr = dynamic_cast<B*>(someAOrBPtr);
if( testBPtr ){
// our suspicions are confirmed -- it really was a B
C->method(testBPtr);
}else{
// our suspicions were incorrect -- it is definitely not a B.
// The someAOrBPtr points to an instance of some other child class of the base A.
C->method(someAOrBPtr);
};
EDIT: In fact, I'll probably do the dynamic cast inside the C->method so there is only one
C::method(A* ptrOfBase)
and then do the appropriate thing (taking in or out the respective container-member-variable of C) inside the one 'method' of C.
Compiler is not smart enough to guess which method you wanna call. In the same situation of yours, you might actually want to call the the first version since you are using a A*. This leaves the programmer to work on: be specific. If you don't want to use ptr (which call the second version as you wished), you need to specifically cast it:
c.method(*((B*)ptrToB));
or better using dynamic cast:
c.method(*dynamic_cast<B*>(ptrToB));
This could be unsafe because you are "downcasting" in which case dynamic cast may throw exception and C style cast won't but will cause memory leak. You have to be very careful.

c++ additional features in subclass not in superclass

Suppose I have the following code:
class A
{
public:
void Funct1();
};
class B : public A
{
public:
void Func1();
void Func2();
}
In main()
Declaring Object of type A
A b = new B;
b.Func1() // can access it;
b.Func2() // cannot access
How can I make or access Func2 using object b especially in main
There are a few problems in your code.
You are using Void instead of void. Notice the uppercase vs lowercase difference.
You are using Funct1 in A but Func1 in B. You can change Funct1 to Func1
There is a missing ; at the end of B.
Using B instead of new B. You have:
A b = new B;
That is a syntactically incorrect line. You can make it either
A b = B();
or
A* b = new B();
Even after that change, you still have the problems you described.
There are two ways you can solve this:
Use B b instead A b.
B b;
b.Func1();
b.Func2();
Use a virtual member function.
class A
{
Public:
void Func1();
virtual void Func2();
};
class B : public A
{
Public:
void Func1();
virtual void Func2();
};
Then, you can use:
B b;
A* aPtr = &b;
aPtr->Func1();
aPtr->Func2();
You may use static_cast
A *b = new B;
B *bb = static_cast<B*> (b);
through bb you can access Func2().
Write a function which gets argument of Type A. Then you can send an argument of type A or B to this function,polymorphism works and the function inside class A or B works wrt what you want.
In a statically typed language like C++, you can only call methods corresponding to the static type of an object in the current scope. In main, you declared b with static type A, restricting it to the interface defined in class A. If you want polymorphism, you need to declare the polymorphic functions in A and also add the virtual keyword.
If object-oriented programming doesn't make sense for the problem you are trying to solve, don't use it. In C++, you don't need to put everything in classes, let alone in class hierarchies. Start with simple free-standing functions and use classes if you need them.
That being said, if you really insist, use dynamic_cast. In some situations, this may even be a legitimate choice. But if you feel that you need it all the time, then you must review your understanding of object-oriented programming.

Can you explain how the methods of the class are called?

conv.h
class Base
{
public:
void foo();
};
class Derived: public Base
{
public:
void bar();
};
class A {};
class B
{
public:
void koko();
};
conv.cpp
void Base::foo()
{
cout<<"stamm";
}
void Derived::bar()
{
cout<<"bar shoudn't work"<<endl;
}
void B::koko()
{
cout<<"koko shoudn't work"<<endl;
}
main.cpp
#include "conv.h"
#include <iostream>
int main()
{
Base * a = new Base;
Derived * b = static_cast<Derived*>(a);
b->bar();
Derived * c = reinterpret_cast<Derived*>(a);
c->bar();
A* s1 = new A;
B* s2 = reinterpret_cast<B*>(s1);
s2->koko();
}
output:
bar shoudn't work
bar shoudn't work
koko shoudn't work
How come the method bar is succeeded to be called in run time despite that I have created a Base class not derived?? it works even with two types of conversions (static and reinterpret cast).
same question as above but with unrelated classes (A & B) ??
Undefined behaviour can do anything, including appear to work.
It's working (read: "compiling and not crashing") 'cause you never use the this pointer in your nominally "member" functions. If you tried to print out a member variable, for example, you'd get the garbage output or crashes you expect - but these functions as they are now don't depend on anything in the classes they're supposedly part of. this could even be NULL for all they care.
The compiler knows a Derived can use member functions foo() and bar() and knows where to find them. After you did your "tricks", you had pointers to Derived.
The fact that they were pointers of type Derived -- regardless of what data was associated with those pointers -- allowed them to call the functions foo() and kook() associated with Derived.
As has been mentioned, if you had actually used the data at the pointers (i.e. read or wrote data members relative to this belonging to the Derived class (which you don't have in this case), you would have been access memory that didn't belong to your objects.

dependent classes as other class members

I have a class B that requires an instance of class A to be constructed:
class B
{
B(A* a); // there is no default constructor
};
Now I want to create a class that contains B as a member, so I also need to add A as a member and provide it to B's constructor:
class C
{
C() : a(), b(&a) {}
A a; // 1. initialized as a()
B b; // 2. initialized as b(&a) - OK
};
But the problem is that if someone occasionally changes the order of the variables definition in the class, it will break
class C
{
C() : a(), b(&a) {}
B b; // 1. initialized as b(&a) while "a" uninitialized
A a; // too late...
};
Is there a good way to resolve this without modifying the classes A and B? Thanks.
Is there a good way to resolve this without modifying the classes A and B?
Turn on compiler warnings; for gcc, this is -Wreorder (which is included in -Wall):
cc1plus: warnings being treated as errors
t.cpp: In constructor 'A::A()':
Line 3: warning: 'A::y' will be initialized after
Line 3: warning: 'int A::x'
Line 2: warning: when initialized here
Alternatively, use a lint-like tool that detects this.
But the problem is that if someone occasionally changes the order of the variables definition in the class…
Why would they do this? I suspect you're worrying too much about what might happen. Even so, you can leave a comment in the class:
A a; // Must be listed before member 'b'!
B b;
Don't underestimate the force of well-placed comments. :) Then allow someone who purposefully ignores them to get what they deserve; you are using C++, after all.
Use the well-known C++ idiom called Base-from-Member to solve this problem.
Define a base class as,
class C_Base
{
A a; //moved `A a` to the base class!
C_Base() : a() {}
};
class C : public C_Base
{
C() : b(&a) {}
B b; // 1. initialized as b(&a) while "a" uninitialized
//A a; // too late...
};
Now, a is guaranteed to be initialized before b.
Store b in a unique_ptr, and set it in the body, not in the initializer list:
class C
{
C() :a() {
b = std::unique_ptr<B>(new B(&a));
}
A a;
std::unique_ptr<B> b;
};
One option would be to not explicitly store the A, but instead to use dynamic allocation to create a new A to store in the B:
class C {
public:
C() : b(new A) {
// handled in initialization list
}
private:
B b;
};
Since this guarantees that the A is created before the B, this should prevent this problem from ever occurring.
The problem is that you are shooting yourself in the foot with the third example. In C++ the order of member variables in a class/struct matters. No matter how you go about solving your particular problem, if you pass uninitialized data to a constructor due to poor class design / member layout, you will be working with unitialized data and possibly get undefined behavior, depending on the sort of code in place.
To address your particular example, if B really requires an A and the relationship is one to one, why not create a new class AB that has both an A object and a B object in the right order and pass the address of A to B. That is:
class AB
{
public:
AB():b_(&a_) {}
private:
A a_;
B b_;
};
now class C can avoid the ordering problem by using AB instead of A and B:
class C
{
public:
...
private:
AB ab_;
};
As forementioned, this of course assumes a 1:1 relationship between A and B. If an A object can be shared by many B objects, things get more complicated.
I'm not sure how much control you have over the implementation and structure of C but is it necessary to use the objects themselves in class C? Could you redefine the class to use pointers instead and then move them from the initialization list, e.g.
class C
{
C()
{
a = new A;
b = new B(a);
}
~C() {delete a; delete b;}
A* a;
B* b;
};
This avoids the issue of order in the declaration, but gives you the new issue of ensuring they're created correctly. Also, if you create A LOT of C's very often, an initialization list is slightly faster.

Trouble understanding C++ `virtual`

I'm having trouble understanding what the purpose of the virtual keyword in C++. I know C and Java very well but I'm new to C++
From wikipedia
In object-oriented programming, a
virtual function or virtual method is
a function or method whose behavior
can be overridden within an inheriting
class by a function with the same
signature.
However I can override a method as seen below without using the virtual keyword
#include <iostream>
using namespace std;
class A {
public:
int a();
};
int A::a() {
return 1;
}
class B : A {
public:
int a();
};
int B::a() {
return 2;
}
int main() {
B b;
cout << b.a() << endl;
return 0;
}
//output: 2
As you can see below, the function A::a is successfully overridden with B::a without requiring virtual
Compounding my confusion is this statement about virtual destructors, also from wikipedia
as illustrated in the following example,
it is important for a C++ base class
to have a virtual destructor to ensure
that the destructor from the most
derived class will always be called.
So virtual also tells the compiler to call up the parent's destructors? This seems to be very different from my original understanding of virtual as "make the function overridable"
Make the following changes and you will see why:
#include <iostream>
using namespace std;
class A {
public:
int a();
};
int A::a() {
return 1;
}
class B : public A { // Notice public added here
public:
int a();
};
int B::a() {
return 2;
}
int main() {
A* b = new B(); // Notice we are using a base class pointer here
cout << b->a() << endl; // This will print 1 instead of 2
delete b; // Added delete to free b
return 0;
}
Now, to make it work like you intended:
#include <iostream>
using namespace std;
class A {
public:
virtual int a(); // Notice virtual added here
};
int A::a() {
return 1;
}
class B : public A { // Notice public added here
public:
virtual int a(); // Notice virtual added here, but not necessary in C++
};
int B::a() {
return 2;
}
int main() {
A* b = new B(); // Notice we are using a base class pointer here
cout << b->a() << endl; // This will print 2 as intended
delete b; // Added delete to free b
return 0;
}
The note that you've included about virtual destructors is exactly right. In your sample there is nothing that needs to be cleaned-up, but say that both A and B had destructors. If they aren't marked virtual, which one is going to get called with the base class pointer? Hint: It will work exactly the same as the a() method did when it was not marked virtual.
You could think of it as follows.
All functions in Java are virtual. If you have a class with a function, and you override that function in a derived class, it will be called, no matter the declared type of the variable you use to call it.
In C++, on the other hand, it won't necessarily be called.
If you have a base class Base and a derived class Derived, and they both have a non-virtual function in them named 'foo', then
Base * base;
Derived *derived;
base->foo(); // calls Base::foo
derived->foo(); // calls Derived::foo
If foo is virtual, then both call Derived::foo.
virtual means that the actual method is determined runtime based on what class was instantiated not what type you used to declare your variable.
In your case this is a static override it will go for the method defined for class B no matter what was the actual type of the object created
So virtual also tells the compiler to call up the parent's destructors? This seems to be very different from my original understanding of virtual as "make the function overridable"
Your original and your new understanding are both wrong.
Methods (you call them functions) are always overridable. No matter if virtual, pure, nonvirtual or something.
Parent destructors are always called. As are the constructors.
"Virtual" does only make a difference if you call a method trough a pointer of type pointer-to-baseclass. Since in your example you don't use pointers at all, virtual doesn't make a difference at all.
If you use a variable a of type pointer-to-A, that is A* a;, you can not only assign other variables of type pointer-to-A to it, but also variables of type pointer-to-B, because B is derived from A.
A* a;
B* b;
b = new B(); // create a object of type B.
a = b; // this is valid code. a has still the type pointer-to-A,
// but the value it holds is b, a pointer to a B object.
a.a(); // now here is the difference. If a() is non-virtual, A::a()
// will be called, because a is of type pointer-to-A.
// Whether the object it points to is of type A, B or
// something entirely different doesn't matter, what gets called
// is determined during compile time from the type of a.
a.a(); // now if a() is virtual, B::a() will be called, the compiler
// looks during runtime at the value of a, sees that it points
// to a B object and uses B::a(). What gets called is determined
// from the type of the __value__ of a.
As you can see below, the function A::a is successfully overridden with B::a without requiring virtual
It may, or it may not work. In your example it works, but it's because you create and use an B object directly, and not through pointer to A. See C++ FAQ Lite, 20.3.
So virtual also tells the compiler to call up the parent's destructors?
A virtual destructor is needed if you delete a pointer of base class pointing to an object of derived class, and expect both base and derived destructors to run. See C++ FAQ Lite, 20.7.
You need the virtual if you use a base class pointer as consultutah (and others while I'm typing ;) ) says it.
The lack of virtuals allows to save a check to know wich method it need to call (the one of the base class or of some derived). However, at this point don't worry about performances, just on correct behaviour.
The virtual destructor is particulary important because derived classes might declare other variables on the heap (i.e. using the keyword 'new') and you need to be able to delete it.
However, you might notice, that in C++, you tend to use less deriving than in java for example (you often use templates for a similar use), and maybe you don't even need to bother about that. Also, if you never declare your objects on the heap ("A a;" instead of "A * a = new A();") then you don't need to worry about it either. Of course, this will heavily depend on what/how you develop and if you plan that someone else will derive your class or not.
Try ((A*)&b).a() and see what gets called then.
The virtual keyword lets you treat an object in an abstract way (I.E. through a base class pointer) and yet still call descendant code...
Put another way, the virtual keyword "lets old code call new code". You may have written code to operate on A's, but through virtual functions, that code can call B's newer a().
Say you instantiated B but held it as an instance of an A:
A *a = new B();
and called function a() whose implementation of a() will be called?
If a() isn't virtual A's will be called. If a() was virtual the instantiated sub class version of a() would be called regardless of how you're holding it.
If B's constructor allocated tons of memory for arrays or opened files, calling
delete a;
would ensure B's destructor was called regardless as to how it was being held, be it by a base class or interface or whatever.
Good question by the way.
I always think about it like chess pieces (my first experiment with OO).
A chessboard holds pointers to all the pieces. Empty squares are NULL pointers. But all it knows is that each pointer points a a chess piece. The board does not need to know more information. But when a piece is moved the board does not know it is a valid move as each pice has different characteristica about how it moves. So the board needs to check with the piece if the move is valid.
Piece* board[8][8];
CheckMove(Point const& from,Point const& too)
{
Piece* piece = board[from.x][from.y];
if (piece != NULL)
{
if (!piece->checkValidMove(from,too))
{ throw std::exception("Bad Move");
}
// Other checks.
}
}
class Piece
{
virtual bool checkValidMove(Point const& from,Point const& too) = 0;
};
class Queen: public Piece
{
virtual bool checkValidMove(Point const& from,Point const& too)
{
if (CheckHorizontalMove(from,too) || CheckVerticalMoce(from,too) || CheckDiagonalMove(from,too))
{
.....
}
}
}