Variables defined in if-cases leak? (aka why does this even compile?) - c++

It seem that variables declared inside an if-statement leaks to the following statement?
I copy-pasted some code and to my surprise it compiled, when it shouldn't have!
I was about to commit the code and lucily I caught the error before that. Below here is a working (?) program that shows the problem.
The following code snippet calls a function on an object that doesn't exist:
#include <iostream>
class A {
public:
virtual ~A() {}
};
class B : public A {
public:
void fooB() { std::cout << "fooB\n"; }
};
class C : public A {
public:
void fooC() { std::cout << "fooC\n"; }
};
int main() {
A* a = new C();
if (B* b = dynamic_cast<B*>(a)) {
b->fooB();
} else if (C* c = dynamic_cast<C*>(a)) {
c->fooC();
b->fooB();
}
return 0;
}
It compiles and the output is thus:
fooC
fooB
This is surely wrong. Do I need to enable some warning(s) to prevent this code from compiling?
Imagine the horrors if I tried to access some member variables or call a virtual function!
Same behaviour both in VS2008 an GCC 4.8

It does exist, but b is NULL on the else branch, and calling a function on it is undefined behavior.

Related

How to implement factory+decorator pattern in c++11

I decided to study/translate Head First Design Patterns' Java code to C++11, and I was able to implement most of the patterns using automatic memory management thanks to smart pointers. However, I have a problem with one of the examples. Here is my code:
#include <iostream>
#include <memory>
class AbstractBase {
public:
virtual void foo() = 0;
virtual ~AbstractBase() = default;
};
class A : public AbstractBase {
public:
void foo() override { std::cout << "Class A: foo() called" << std::endl; }
};
class B : public AbstractBase {
public:
void foo() override { std::cout << "Class B: foo() called" << std::endl; }
};
class FooDecorator : public AbstractBase {
public:
FooDecorator(AbstractBase *pBase): mpBase(pBase) { }
void foo() override
{
mpBase->foo();
++mNumberOfFooCalls;
}
static int getFooCalls() { return mNumberOfFooCalls; }
private:
static int mNumberOfFooCalls;
AbstractBase *mpBase;
};
class AbstractFactory {
public:
virtual std::unique_ptr<AbstractBase> createA() = 0;
virtual std::unique_ptr<AbstractBase> createB() = 0;
virtual ~AbstractFactory() = default;
};
class CountingFactory : public AbstractFactory {
public:
std::unique_ptr<AbstractBase> createA()
{
// auto pA = new A();
// return std::unique_ptr<AbstractBase>(new FooDecorator(pA));
std::unique_ptr<AbstractBase> pA(new A());
return std::unique_ptr<AbstractBase>(new FooDecorator(pA.get()));
}
std::unique_ptr<AbstractBase> createB()
{
// auto pB = new B();
// return std::unique_ptr<AbstractBase>(new FooDecorator(pB));
std::unique_ptr<AbstractBase> pB(new B());
return std::unique_ptr<AbstractBase>(new FooDecorator(pB.get()));
}
};
int FooDecorator::mNumberOfFooCalls = 0;
int main()
{
std::unique_ptr<AbstractFactory> pFactory(new CountingFactory());
std::unique_ptr<AbstractBase> pObjA = pFactory->createA();
std::unique_ptr<AbstractBase> pObjB = pFactory->createB();
pObjA->foo();
pObjB->foo();
std::cout << "Foo called " << FooDecorator::getFooCalls()
<< " times." << std::endl;
}
What this code does essentially is; there are two derived classes A and B; and they each have a single member function that shows which one has been called. There is also a decorator called FooDecorator that adds capability to count calls made to foo().
In addition to these, there is also CountingFactory which is used to get decorated objects directly.
In the main part, using this factory, I create an instance of A and an instance of B. Then call foo() from each.
When I compile this code using clang 3.5 and run it, I do not get any errors, but the result is a bit different than expected as it calls B::foo() twice:
Class B: foo() called
Class B: foo() called
Foo called 2 times.
On the other hand, when I compile the code using gcc 4.9.2 and run it, I get the following error:
pure virtual method called
terminate called without an active exception
It looks like the problem is the unique_ptrs inside the CountingFactory. My understanding is the pointer that's used to initialize the decorated object gets freed and it leads to either undefined behavior (clang case) or termination (gcc case).
As a result, I decided to use raw pointers and added the (commented-out above) lines:
auto pA = new A();
return std::unique_ptr<AbstractBase>(new FooDecorator(pA));
auto pB = new B();
return std::unique_ptr<AbstractBase>(new FooDecorator(pB));
Doing this, things worked successfully, I got the expected output from both compilers. However, now there is a memory leak, and the allocations must be deleted.
Having almost always found a solution with smart pointers to problems like these, I am struggling to come up with the best approach to this issue. I also tried replacing unique_ptrs with shared_ptrs, but to no avail, it did not work.
Can I still get away with smart pointers following a different approach? Or do I have to manually manage the memory I allocated inside the factory (not preferred)?
As I understand, you need FooDecorator to take ownership of pBase. You can achieve this by changing
AbstractBase *mpBase;
to
std::unique_ptr<AbstractBase> mpBase;
So you create FooDecorator in CountingFactory like this:
return std::unique_ptr<AbstractBase>(new FooDecorator(new A()));
Or in C++14:
return std::make_unique<FooDecorator>(new A());
The reason for the crash is that you just assign the inner pointer via get method.
std::unique_ptr<AbstractBase> pB(new B());
return std::unique_ptr<AbstractBase>(new FooDecorator(pB.get()));
Which means that when scope ends, the memory of your inner B (or A) is gets deleted.
What you can do is call release instead.
But yeah to avoid the leak you should have a unique_ptr in your FooDecorator as well.
Live on IdeOne

How can an object type be unknown at compile time?

I am currently learning about dynamic binding and virtual functions. This is from Accelerated C++, chapter 13:
[...] We want to make that decision at run time. That is, we want the
system to run the right function based on the actual type of the
objects passed to the function, which is known only at run time.
I don't understand the very idea that the type of an object can be unknown at compile time. Isn't it obvious from the source code?
Not at all. Consider this example:
struct A {
virtual void f() = 0;
};
struct B : A {
virtual void f() { std::cerr << "In B::f()\n"; }
};
struct C : A {
virtual void f() { std::cerr << "In C::f()\n"; }
};
static void f(A &a)
{
a.f(); // How do we know which function to call at compile time?
}
int main(int,char**)
{
B b;
C c;
f(b);
f(c);
}
When the global function f is compiled, there is no way to know which function it should call. In fact, it will need to call different functions each time. The first time it is called with f(b), it will need to call B::f(), and the second time it is called with f(c) it will need to call C::f().
C++ has a concept of pointers, where the variable holds only a "handle" to an actual object. The type of the actual object is not known at compile-time, only at runtime. Example:
#include <iostream>
#include <memory>
class Greeter {
public:
virtual void greet() = 0;
};
class HelloWorld : public Greeter {
public:
void greet() {std::cout << "Hello, world!\n";}
};
class GoodbyeWorld : public Greeter {
public:
void greet() {std::cout << "Goodbye, world!\n";}
};
int main() {
std::unique_ptr<Greeter> greeter(new HelloWorld);
greeter->greet(); // prints "Hello, world!"
greeter.reset(new GoodbyeWorld);
greeter->greet(); // prints "Goodbye, world!"
}
See also: Vaughn Cato's answer, which uses references (which is another way to hold a handle to an object).
Say you have a pointer to base class pointing to a derived object
Base *pBase = new Derived;
// During compilation time, compiler looks for the method CallMe() in base class
// if defined in class Base, compiler is happy, no error
// But when you run it, the method call gets dynamically mapped to Derived::CallMe()
// ** provided CallMe() is virtual method in Base and derived class overrides it.
pBase->CallMe(); // the actual object type is known only during run-time.

Polymorphic Member Variable

I got an elegant answer yesterday for my question regarding polymorphic object members.
But now I am facing the problem that the variable isn't really behaving the way I expected it to. The following code is being used:
#include <iostream>
#include <math.h>
using std::cin;
using std::cout;
using std::endl;
class Com
{
public:
virtual void setReady()
{
cout << "Com" << endl;
}
};
class DerivedCom : public Com
{
public:
void setReady()
{
cout << "DCom" << endl;
}
void somethingElse()
{
cout << "else" << endl;
}
};
class BaseClass
{
public:
Com* com;
public:
BaseClass(Com* c = new Com) : com(c)
{
}
virtual void setReady()
{
com->setReady();
}
};
class DerivedClass : public BaseClass
{
// the call to somethingElse() won't compile if I leave out this declaration
protected:
DerivedCom* com;
public:
DerivedClass() : BaseClass(new DerivedCom)
{
}
void setReady()
{
// This line causes a segfault if I put in the declaration earlier
this->com->setReady();
// This line won't compile if I leave out the declaration earlier
this->com->somethingElse();
}
};
int main()
{
DerivedClass* inst = new DerivedClass();
inst->setReady();
return 0;
}
The problem is, that DerivedClass::com is in fact of type DerivedCom but I can't access any DerivedCom-specific methods as the compiler won't find them. If I put in an extra re-declaration DerivedCom* com, the compiler will find the methods but I get segmentation faults.
Remove that extra declaration.
If you are sure that a Com* is a DerivedCom* then you can static_cast it.
static_cast<DerivedCom*>(this->com)->somethingElse();
This will likely crash it you're wrong however. So if you are not sure then you can dynamic_cast it
DerivedCom* dcom = dynamic_cast<DerivedCom*>(this->com);
if (dcom)
dcom->somethingElse();
dynamic_cast will return NULL if the object isn't of the type you asked for.
The reason for the segmentation faults is that you arent declaring the variable again with a different type, you are actually defining a new pointer in the derived class, one that is never initialized. Thus this->com->... will access the derived class com and crash since it is an uninitialized pointer.
What you are trying to do though, is to change the type of the member pointer. You could do that by making the type of the member pointer as a template variable, as follows
template <class ComType>
class BaseClassTemplate
{
ComType* com;
...;
};
typedef BaseClassTemplate<Com> BaseClass;
class DerivedClass : public BaseClassTemplate<DerivedCom>
{
...;
};
However this makes the base class a template, so to get it as you want it, you need to make an instantiation of BaseClass<Com> to get your version of base class. You can either make it a derived class or just a typedef as i have shown.

C++: Default values in class member

I have a problem with specifying the default values for my C++ class members. My code is:
From Someclass.h:
class SomeClass
{
public:
SomeClass();
~SomeClass();
void printOut (bool);
}
...from SomeClass.cpp:
void SomeClass::printOut(bool foobar=true)
{
if (foobar) { std::cout << foobar << std::endl; }
}
...and finally, from main.cpp:
int main()
{
SomeClass s;
s.printOut();
return 0;
}
This however gives error message (gcc):
../main.cpp: In function `int main()':
../main.cpp:8: error: no matching function for call to `SomeClass::printOut()'
../SomeClass.h:18: note: candidates are: void SomeClass::printOut(bool)
subdir.mk:21: recipe for target `main.o' failed
make: *** [main.o] Error 1
I have tried specifying the default value directly into the class declaration in the header file, etc. I also tried searching both Stack Overflow and Google in general, but cannot find any solution anywhere. What am I doing wrong?
You haven't specified the default value for the parameter in the header as such, the compiler is looking for a function of signature void printOut(void) for your statement s.printOut(); but correctly not finding it. What you need is:
class SomeClass
{
public:
SomeClass();
~SomeClass();
void printOut( bool fValue = true ); // Note change in param in definition
}
And in your cpp :
void SomeClass::printOut(bool foobar /*=true*/ )
{
if (foobar) { std::cout << foobar << std::endl; }
}
As a side note, bear in mind you don't have to put the commented out default value for the parameter in the implementation file but it is a good idea for readability.
You need to declare the default value inside the class definition, not in the implementation.
class SomeClass
{
public:
SomeClass();
~SomeClass();
void printOut (bool foobar = true); //move default here
}
void SomeClass::printOut(bool foobar) //remove from here
{
if (foobar) { std::cout << foobar << std::endl; }
}
Also, note that:
SomeClass s();
doesn't do what you expect it to do. It doesn't create an object s of type SomeClass, but declares a function s with return type SomeClass. s.printOut(); shouldn't compile.
You probably want:
SomeClass s;
Default value must be specified in the declaration of the method, not in the implementation.
Default parameters must be defined in the header like this:
class SomeClass
{
public:
SomeClass();
~SomeClass();
void printOut (bool value = true);
}
rewrite as follow .. note bool b=false
class SomeClass
{
public:
SomeClass();
~SomeClass();
void printOut (bool b=false);
}
Try to specify default value in header file:
class SomeClass
{
public:
SomeClass();
~SomeClass();
void printOut (bool foobar=true);
}
the default value has to be specified in the declaration and not in the definition. You can specify default value at both the places but cant omit from definition. hope i dint confuse you. I will show the e\corrected code so you can understand:
class SomeClass
{
public:
SomeClass();
~SomeClass();
void printOut (bool foobar = true);
}
...from SomeClass.cpp:
void SomeClass::printOut() //or you can use: void SomeClass::printOut(bool foobar=true)
{
if (foobar) { std::cout << foobar << std::endl; }
}
...and finally, from main.cpp:
int main()
{
SomeClass s();
s.printOut();
return 0;
}

calling member function without object error: C++ / (G++) oop

i was curious to know why the following throws an error in g++ (cannot call member function without object). I suppose a workaround would be to have the B class variable as static variable in A - but i was curious to find out why, when there is an instance of A's child class C created, this still throws an error - many thanks!
#include <iostream>
#include <cstring>
using namespace std;
class B {
public:
double var;
public:
friend class A;
B() : var(1) { };
void set(double new_rate);
};
class A {
protected:
B main_B;
public:
virtual void set_rate(double new_rate) { cout << "test";
//B.set(new_rate);
}
};
class C : public A {
};
/*
void B::set(double new_rate) {
var = new_rate;
cout << "worked " <<current_rate <<endl;
}
*/
int main() {
C test_C;
A::set_rate ( 2.00 );
return 0;
}
Firstly,
C test_c();
does not create an instance of C, it declares a function that returns a C. You mean:
C test_c;
Secondly, non-static member functions can only be called on a specific instance of a class. So with the corrected code, you could say:
test_c.set_rate( 2.0);
You can use an explicit <class>:: to call a non-static member function, thereby disabling any virtual function mechanism, but for a non-static member you still need to specify a class instance on which to call the function.
e.g.
int main()
{
C test_C;
test_C.A::set_rate(2.00);
return 0;
}