a link error in C++ programming
-
I create an abstract class and a class derived from it. I know that an abstract class's object cannot be created until all its pure virtual functions are redefined within their derived class. However, How about the constructor and destructor functions? As they are special class functions, they can not be redefined within their derived class. class Abstract_base { public: virtual ~Abstract_base()=0; virtual void interface1() const = 0; virtual const char* mumber() const { return _mumble; }; protected: char *_mumble; }; class Concrete_derived : public Abstract_base { public: Concrete_derived() { }; virtual void interface1() const {}; }; int main { Concrete_derived trouble; return 0; } The code above has link eror.(error LNK2019) If I change "virtual ~Abstract_base()=0;" to "virtual ~Abstract_base()=0; {}", the link error disappeared. Why shall we add "virtual" to the destructor function? Can you give me some explanation? many thanks Tomorrow is another day!
-
I create an abstract class and a class derived from it. I know that an abstract class's object cannot be created until all its pure virtual functions are redefined within their derived class. However, How about the constructor and destructor functions? As they are special class functions, they can not be redefined within their derived class. class Abstract_base { public: virtual ~Abstract_base()=0; virtual void interface1() const = 0; virtual const char* mumber() const { return _mumble; }; protected: char *_mumble; }; class Concrete_derived : public Abstract_base { public: Concrete_derived() { }; virtual void interface1() const {}; }; int main { Concrete_derived trouble; return 0; } The code above has link eror.(error LNK2019) If I change "virtual ~Abstract_base()=0;" to "virtual ~Abstract_base()=0; {}", the link error disappeared. Why shall we add "virtual" to the destructor function? Can you give me some explanation? many thanks Tomorrow is another day!
You shouldn't put a
=0
after your destructor. This means that the function is a pure virtual function: the function be implemented by all child classes. It is quite odd to put that on a destructor. A destructor is always required (one is supplied by default if you don't write it yourself) so, you need to provide a body. Which you did by adding{}
. This is just an empty body, but it is still a body. If you don't provide a body for your destructor, you'll get a linker error.
Cédric Moonen Software developer
Charting control [v1.2] -
You shouldn't put a
=0
after your destructor. This means that the function is a pure virtual function: the function be implemented by all child classes. It is quite odd to put that on a destructor. A destructor is always required (one is supplied by default if you don't write it yourself) so, you need to provide a body. Which you did by adding{}
. This is just an empty body, but it is still a body. If you don't provide a body for your destructor, you'll get a linker error.
Cédric Moonen Software developer
Charting control [v1.2] -
I create an abstract class and a class derived from it. I know that an abstract class's object cannot be created until all its pure virtual functions are redefined within their derived class. However, How about the constructor and destructor functions? As they are special class functions, they can not be redefined within their derived class. class Abstract_base { public: virtual ~Abstract_base()=0; virtual void interface1() const = 0; virtual const char* mumber() const { return _mumble; }; protected: char *_mumble; }; class Concrete_derived : public Abstract_base { public: Concrete_derived() { }; virtual void interface1() const {}; }; int main { Concrete_derived trouble; return 0; } The code above has link eror.(error LNK2019) If I change "virtual ~Abstract_base()=0;" to "virtual ~Abstract_base()=0; {}", the link error disappeared. Why shall we add "virtual" to the destructor function? Can you give me some explanation? many thanks Tomorrow is another day!
richardye wrote:
Can you give me some explanation?
You must provide a definition of the pure virtual destructor.
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
-
I create an abstract class and a class derived from it. I know that an abstract class's object cannot be created until all its pure virtual functions are redefined within their derived class. However, How about the constructor and destructor functions? As they are special class functions, they can not be redefined within their derived class. class Abstract_base { public: virtual ~Abstract_base()=0; virtual void interface1() const = 0; virtual const char* mumber() const { return _mumble; }; protected: char *_mumble; }; class Concrete_derived : public Abstract_base { public: Concrete_derived() { }; virtual void interface1() const {}; }; int main { Concrete_derived trouble; return 0; } The code above has link eror.(error LNK2019) If I change "virtual ~Abstract_base()=0;" to "virtual ~Abstract_base()=0; {}", the link error disappeared. Why shall we add "virtual" to the destructor function? Can you give me some explanation? many thanks Tomorrow is another day!
Destructors *are* different from normal memeber functions. If you have a normal member function, you can choose whether to call the ancestor's implementation or not. eg:
void CMyDialog::DoDataExchange (CDataExchange *pDX)
{
....
CDialog::DoDataExchange (pDX);
}While it's good practise to call the ancester method in the example above, it's not required to by C++ - so DoDataExchange could have been a virtual =0 member. BUT... Destructor's don't get the choice of whether to call the ancester destructor or not. When CMyDialog::~CMyDialog is finished, CDialog::~CDialog is run whether you want it or not. In which case, it needs to exist - even if it's very boring (eg
{ }
) as you've found out. I hope that helps a little. Iain. -
Cedric Moonen wrote:
It is quite odd to put that on a destructor.
What? It is exactly what any abstract base class should have. Did you ever read Effective C++ by Scott Meyers?
led mike wrote:
Did you ever read Effective C++ by Scott Meyers?
Nope but I was planning to buy it soon :-D
led mike wrote:
It is exactly what any abstract base class should have.
Yes, I see. I never done it that way: I always used at least one pure virtual function.
Cédric Moonen Software developer
Charting control [v1.2] -
Destructors *are* different from normal memeber functions. If you have a normal member function, you can choose whether to call the ancestor's implementation or not. eg:
void CMyDialog::DoDataExchange (CDataExchange *pDX)
{
....
CDialog::DoDataExchange (pDX);
}While it's good practise to call the ancester method in the example above, it's not required to by C++ - so DoDataExchange could have been a virtual =0 member. BUT... Destructor's don't get the choice of whether to call the ancester destructor or not. When CMyDialog::~CMyDialog is finished, CDialog::~CDialog is run whether you want it or not. In which case, it needs to exist - even if it's very boring (eg
{ }
) as you've found out. I hope that helps a little. Iain.You mean that no matter how I should define the pure destructor function. But there is still something I cannot understand very well. If in your class you have a pure member function, you must show that any class derived from it should implement your pure function. Isn't it? But if you define a destructor function to be pure, you cannot implement it in your derived class and you have to add "{}" in your base class. I think it is meaningless. Why shall we use pure destructor function in a class? Many thanks. Tomorrow is another day!