Calling member variable's virtual function within destructor causes seg fault - c++

I'm having a very odd problem that I'm hoping someone has come across.
class Letter
{
public:
Letter()
virtual ~Letter()
virtual std::string get() const = 0;
};
class A : public Letter
{
public:
A()
~A()
virtual std::string get() const { return "A"; }
};
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
delete letter;
}
void setLetter(Letter * l) { letter = l }
private:
Letter * letter;
}
int main()
{
Board b;
b.setLetter(new A());
}
The program causes a seg fault when Board goes out of scope at the line where the virtual function letter->get() is called in the destructor. I'm using gcc 4.1.2. Any ideas?
UPDATE
Okay, it seems what's actually happening in the real code is the equivalent of this:
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter* letter;
};
int main()
{
Board b;
A a;
b.setLetter(&a);
return 0;
}
In which case A is already out of scope when the virtual function is called.

I can only guess you're attempting to cast the std::string returned from get() to a char*. Otherwise i see no reason for the crash.

#include <iostream>
#include <string>
using namespace std;
class Letter
{
public:
Letter() {}
virtual ~Letter() {}
virtual std::string get() const = 0;
};
class A : public Letter
{
public:
A() {}
~A() {}
virtual std::string get() const { return "A"; }
};
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
delete letter;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter * letter;
};
int main()
{
Board b;
b.setLetter(new A());
return 0;
}
no problem in gcc 4.5.2

I didn't realize an object was being passed to setLetter() from the stack, so A was going out of scope before b.
Board b;
A a;
b.setLetter(&a);

Some compilers doesn't allow Plain C / C++ constructors or destructors call virtual methods, seems like the (ANSI) C++ specification neither. And its not recommended.
Sometimes that requirement is useful. Some languages like Object Pascal explicit allow virtual methods calls within constructors and destructors.
One thing you can do its use the "Fake Virtual Constructor Pattern":
class MyClass
{
public:
// constructor
MyClass
{
// anything but virtual methods
}
// destructor
~MyClass
{
// anything but virtual methods
}
virtual void MyFakeConstructor()
{
MyVirtualMethod();
}
virtual void MyFakeDestructor()
{
MyVirtualMethod();
}
virtual void MyVirtualMethod()
{
// more stuff
}
// more members
}
int main(char[][] Args)
{
MyClass MyObject = new MyClass();
MyObject->MyFakeConstructor(); // <-- calls "MyVirtualMethod()"
MyObject->DoSomething1();
MyObject->DoSomething2();
MyObject->DoSomething3();
MyObject->MyFakeDestructor(); // <-- calls "MyVirtualMethod()"
delete MyObject;
return 0;
} // int main()
Another solution its that you arrange your code so you explicit call your virtual method outside the destructor.
Cheers.

Related

Why a derived class B is said not to be a member of its parent class A?

I do not understand why the following code does not work since *p is dynamically a B object.
class A {
public:
bool test() {return true;}
};
class B : public A {
public:
bool test() {return false;}
};
int main() {
A* p = new B;
std::cout << p->B::test();
return 0;
}
I know I could use virtual but I believe this is not the point. The compiler says I should define a second constructor or a conversion operator. What can I do ?
*p is dynamically a B object, but with declaration A* p and usage p->test(), A::test() is statically linked at compile time.
If you want dynamic dispatch at runtime, you have to use virtual functions.
#include<iostream>
class A {
public:
bool test() { return true; }
virtual int count() { return 42; }
};
class B : public A {
public:
bool test() { return false; }
virtual int count() { return 100; }
};
int main() {
A* p = new B();
std::cout << p->test() << std::endl; // A::test() is called
std::cout << p->count(); // B::count() is called
}
In the example, functions bool test() will be dispatched statically, while int count() will be dispatched dynamically.

C++ Manager object and virtual functions

I am trying to wrap my head around using a manager object to loop through the objects in an array and invoke the virtual functions for each object. Here is my code so far, thanks to some very helpful suggestions, it compiles but still doesn't make use of polymorphism the way that I want it to. Thanks in advance for any tips that can point me in the right direction.
#include <iostream>
class avian{
private:
static const int max_birds = 25;
avian* birds[max_birds];
int num_birds;
public:
avian() : num_birds(0){}
virtual ~avian() {
for (int i = 0; i < num_birds; ++i) { delete birds[i]; }
}
bool add(avian* b){
if (num_birds >= max_birds){ return false; }
birds[num_birds++] = b;
return true;
}
void make_bird(){
for (int i = 0; i< num_birds; ++i){birds[i]->make_bird();
}
}
virtual void lay_eggs(){} ;
virtual void bird_noise(){} ;
};
class turkey : public avian{
public:
void lay_eggs() const{ std::cout << "000\n"; }
void bird_noise() const { std::cout << "Gobble Gobble Gobble!\n"; }
};
class chicken : public avian {
public:
void lay_eggs() const { std::cout << "OOOOO\n"; }
void bird_noise() const { std::cout << "Bock Bock Bock!\n"; }
};
class quail : public avian{
public:
void lay_eggs() const { std::cout << "ooooooooo\n"; }
void bird_noise() const { std::cout << "Chirr Chirr Chirr!\n"; }
};
int main(){
avian* my_turkey = new turkey;
my_turkey->make_bird();
my_turkey->lay_eggs();
my_turkey->bird_noise();
delete my_turkey;
return 0;
}
You don't have a virtual base class destructor:
virtual ~avian() { ... }
Calls to delete pointer_to_avian will will call avian::~avian, but they will not propagate to the destructors of derived classes - UB, as compiler says.
avian::lay_eggs is declared, but not defined. Did you mean to make it pure virtual function? You've overriden it in every derived class.
avian::bird_noise - same as above
You forgot to delete my_turkey in main - you're leaking memory.
Your base virtual methods are not marked as const. But methods in derived classes are const. So they are not overriden.
Rule of thumb is to use override keyword in order to avoid such errors

pointer to member and using virtual functions

I want to fill a constexpr table with pointers to call the pointers later. The given example shows only one entry.
I run into two problems:
1) It is not possible for me to find a correct syntax to write a pointer a member class object which is able to initialized to an object of a derived class.
2) I could not use the pointer to call the virtual functions.
#include <iostream>
using namespace std;
class State { public: virtual void Do() const {} };
class S1: public State { public: virtual void Do() const { cout << "S1 Do" << endl; } };
class S2: public State { public: virtual void Do() const { cout << "S2 Do" << endl; } };
class A
{
public:
S1 s1;
S2 s2;
};
class B
{
private:
static constexpr A a{};
static constexpr State A::*state { &A::S2 }; // < do not work!
public:
void Do() const
{
(a.*state).Do(); // is it possible to have a pointer to any State class to call virtual functions?
}
};
constexpr A B::a;
int main()
{
B b;
b.Do();
return 0;
}
I think the issue is an oversite in the standard. There's no
reason why:
State A::*state = static_cast<State A::*>( &A::s1 );
shouldn't work, but the wording to allow it is missing in the
standard. There are a number of work-arounds: the most obvious
would be to have an accessor function returning a State* for
each member variable, and use a pointer to the function:
class A
{
public:
S1 s1;
State* getS1() { return &s1; }
S1 s2;
State* getS2() { return &s2; }
};
class B
{
static A a;
static State* (A::*getState)();
public:
void Do() const
{
(a.*getState)()->Do();
}
}
State* (A::* B::getState)() = &A::getS1;

C++ Override Pure Virtual Function with Function Pointer

If I have a pure virtual function can it be overriden with a function pointer? Scenario below (I'm aware that it's not 100% syntactically correct):
#include<iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
public:
B() { foo = &B::caseOne; }
void caseOne() { cout << "Hello One" << endl; }
void caseTwo() { cout << "Hello Two" << endl; }
void (B::*foo)();
void chooseOne() { foo = &B::caseOne; }
void chooseTwo() { foo = &B::caseTwo; }
};
int main() {
B b;
b.(*foo)();
}
EDIT: In case anyone's interested, here's how I accomplished what I wanted to do:
#include<iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
public:
B() { f = &B::caseOne; }
void caseOne() { cout << "Hello One" << endl; }
void caseTwo() { cout << "Hello Two" << endl; }
void (B::*f)();
void chooseOne() { f = &B::caseOne; }
void chooseTwo() { f = &B::caseTwo; }
void foo() { (this->*f)(); }
};
int main() {
B b;
b.foo();
b.chooseTwo();
b.foo();
}
The output is:
Hello One
Hello Two
No. And you use this wrong. In your code you are trying to assign member-function pointer to function-pointer - it's cannot be compiled.
C++03 standard 10.3/2
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or
indirectly from Base, a member function vf with the same name and same parameter list as Base::vf is
declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides
Base::vf.
As #ForEveR said, your code cannot compile. However, since what you actually need is the ability of switching B's implementation of foo in the runtime, we do have workaround:
#include <iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
private:
void (B::*_f)();
public:
B() { chooseOne(); }
void caseOne() {
cout << "case one" << endl;
}
void caseTwo() {
cout << "case two" << endl;
}
void chooseOne() { _f = &B::caseOne; }
void chooseTwo() { _f = &B::caseTwo; }
void foo() {
(this->*_f)();
}
};
int main(int argc, const char *argv[])
{
A* b = new B();
b->foo();
((B*)b)->chooseTwo();
b->foo();
return 0;
}
UPDATE:
Just found the OP added his answer in the question, which is almost the same as mine. But I think calling foo through pointer instead of instance object is better, for that can exhibit the effect of polymorphism. Besides, it's better to hide f as a private member function.
I think when compile time, the syntax can NOT be compiled. You should provide an override function with the certain name and same args list.

Nested Class member function can't access function of enclosing class. Why?

Please see the example code below:
class A
{
private:
class B
{
public:
foobar();
};
public:
foo();
bar();
};
Within class A & B implementation:
A::foo()
{
//do something
}
A::bar()
{
//some code
foo();
//more code
}
A::B::foobar()
{
//some code
foo(); //<<compiler doesn't like this
}
The compiler flags the call to foo() within the method foobar(). Earlier, I had foo() as private member function of class A but changed to public assuming that B's function can't see it. Of course, it didn't help. I am trying to re-use the functionality provided by A's method. Why doesn't the compiler allow this function call? As I see it, they are part of same enclosing class (A). I thought the accessibility issue for nested class meebers for enclosing class in C++ standards was resolved.
How can I achieve what I am trying to do without re-writing the same method (foo()) for B, which keeping B nested within A?
I am using VC++ compiler ver-9 (Visual Studio 2008). Thank you for your help.
foo() is a non-static member function of A and you are trying to call it without an instance.
The nested class B is a seperate class that only has some access privileges and doesn't have any special knowledge about existing instances of A.
If B needs access to an A you have to give it a reference to it, e.g.:
class A {
class B {
A& parent_;
public:
B(A& parent) : parent_(parent) {}
void foobar() { parent_.foo(); }
};
B b_;
public:
A() : b_(*this) {}
};
This is an automagic, albeit possibly nonportable trick (worked on VC++ since 6.0 though). Class B has to be a member of class A for this to work.
#ifndef OUTERCLASS
#define OUTERCLASS(className, memberName) \
reinterpret_cast<className*>(reinterpret_cast<unsigned char*>(this) - offsetof(className, memberName))
#endif
class A
{
private:
class B
{
public:
void foobar() {
A* pA = OUTERCLASS(A, m_classB);
pA->foo();
}
} m_classB;
public:
foo();
bar();
};
Basically what Georg Fritzsche said
#include <iostream>
#include <cstring>
using namespace std;
class A
{
private:
class B
{
A& parent_;
public:
//B(); //uncommenting gives error
~B();
B(A& parent) : parent_(parent) {}
void foobar()
{
parent_.foo();
cout << "A::B::foo()" <<endl;
}
const std::string& foobarstring(const std::string& test) const
{
parent_.foostring(test); cout << "A::B::foostring()" <<endl;
}
};
public:
void foo();
void bar();
const std::string& foostring(const std::string& test) const;
A();
~A(){};
B b_;
};
//A::B::B() {}; //uncommenting gives error
A::B::~B(){};
A::A():b_(*this) {}
void A::foo()
{
cout << "A::foo()" <<endl;
}
const std::string& A::foostring(const std::string& test) const
{
cout << test <<endl;
return test;
}
void A::bar()
{
//some code
cout << "A::bar()" <<endl;
foo();
//more code
}
int main(int argc, char* argv[])
{
A a;
a.b_.foobar();
a.b_.foobarstring("hello");
return 0;
}
If you uncomment the default B constructor you would get an error
If you want to reuse functionality from A then you should inherit from A not nest B inside it.
Combining Igor Zevaka's and enthusiasticgeek's answers. Also, using reinterpret_cast for calculating offset (If you create class member variable using new keyword):
#include <iostream>
#include <cstring>
using namespace std;
template < typename T, typename U > constexpr size_t offsetOf(U T:: *member)
{
return (char*) &((T*) nullptr->*member) - (char*) nullptr;
}
class A
{
private:
class B
{
public:
B(string message);
~B();
void foobar()
{
A *pA = reinterpret_cast<A*> (reinterpret_cast< unsigned char*> (this) - offsetOf(&A::b_));
pA->foo();
pA->bar();
std::cout << "DONE!";
}
};
public:
void foo();
void bar();
A();
~A() {};
B* b_ = new B("Hello World!");
};
A::A()
{
cout << "A constructor\n";
};
A::B::B(string message) {
cout << "B constructor\n";
cout << "Message = " << message << "\n";
};
A::B::~B() {};
void A::foo()
{
cout << "A::foo()" << endl;
}
void A::bar()
{
cout << "A::bar()" << endl;
foo();
}
int main(int argc, char *argv[])
{
A* a = new A();
a->b_->foobar();
return 0;
}
Output:
B constructor
Message = Hello World!
A constructor
A::foo()
A::bar()
A::foo()
DONE!
References:
https://stackoverflow.com/a/10607424/9524565
https://stackoverflow.com/a/3058382/9524565
https://stackoverflow.com/a/20141143/9524565