什么情况下会出现如此问题:destructors must be member functions ?

jinux 2002-12-25 03:59:47
destructors must be member functions

这是使用g++编译时出现的错误提示,错误提示指向可我在类的声明中的析构函数声明行,这个类派生于一个抽象类,抽象类具有虚析构函数(不是纯虚).

但请各位高手出手指点!
...全文
41 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
ckacka 2003-01-17
  • 打赏
  • 举报
回复
呵呵,你去看看Lippman的书!
chinajiji 2003-01-16
  • 打赏
  • 举报
回复
嘿嘿,我不认同你的说法,
我认为virutal ~Base() = 0与virutal ~Base();的区别仅仅会影响到class Base;对所有以Base为基类的派生类的析构行为二者是完全相同的.
ckacka 2003-01-16
  • 打赏
  • 举报
回复
不对,上面最后一句话有问题。那是针对有成员数据的抽象类!
ckacka 2003-01-16
  • 打赏
  • 举报
回复
"这句话我完全理解,也是正确的,因为去掉virtual ~Base() = 0;后,基类的destructor 就是不virtual的了,派生类的destructor当然可能不会正确调用,"
对于这里,我不是说去掉virtual ~Base() = 0;
而是说去掉 = 0
让它成为virtual,而不是pure virtual,这样,派生类的destructor仍然具有虚函数的性质,而同时不会出现上述的问题。


"如果我将Base的destructor声明为:virutal ~Base() = 0后,你认为在以Base为根基类的派生体系中,如果有一个派生类没有显式声明destructor的话,你认为多态不会正确发生?即不会调用这个派生类的析构函数?"
对于这里,不仅仅是“不会调用这个派生类的析构函数”,而是所有的类的析构函数都会失效。
所以不是说不使用virtual destructor,而是不使用pure virtual destructor,所以在构造抽象类的时候,一般让其他的函数成为pure virtual,但是不要使用const pure virtual。
chinajiji 2003-01-15
  • 打赏
  • 举报
回复
ckacka(小红帽):
你好:
你说:
"如果同时去掉Base::~Base() { cout << "~Base()" << endl; }和virtual ~Base() = 0;就是编译连接都没有问题,但是~Derived() { cout << "~Derived()!" << endl; }的调用无法实现。"
这句话我完全理解,也是正确的,因为去掉virtual ~Base() = 0;后,基类的destructor 就是不virtual的了,派生类的destructor当然可能不会正确调用,
问题的关键是:
如果我将Base的destructor声明为:virutal ~Base() = 0后,你认为在以Base为根基类的派生体系中,如果有一个派生类没有显式声明destructor的话,你认为多态不会正确发生?即不会调用这个派生类的析构函数?
我对你的说法理解对不对?
ckacka 2003-01-15
  • 打赏
  • 举报
回复
至于我在最前面的回答:
“抽象类里面不应该有构造函数和析构函数,因为抽象类根本就不会被实例化。
你把抽象类的构造函数和析构函数去掉!

这个是有问题的,我的表达错误,很对不起!
ckacka 2003-01-15
  • 打赏
  • 举报
回复
你试一试这个

如果同时去掉Base::~Base() { cout << "~Base()" << endl; }和virtual ~Base() = 0;就是编译连接都没有问题,但是~Derived() { cout << "~Derived()!" << endl; }的调用无法实现。

换句话说,如果你创建了一个多层继承体系,每一层都明确通过destructor来实现一些必要的操作的话,那么,如果你其中任意一层中的virtual destructor的定义空白,则出现每一层的virtual destructor都不被调用,当然,前提是"让destructor成为pure virtual绝对是个错误",

再明确一点,如果每一层的virtual destructor都有类似delete([])这样的操作,那么,一次的定义空白,将导致大量的内存垃圾!

你可以构件一个3-4层的继承体系试一试。
ckacka 2003-01-13
  • 打赏
  • 举报
回复
chinajiji(菜鸟叽叽):
你好!
如果在实现上,尽管“被共享的数据”放入基类的确是一种正当的设计,不过我们所付出的代价却是需要明确的写出一个构造函数来初始化数据来维护封装。所以,我们尽可能地把数据剥离出来,只在虚基类里面放入操作,也就是只允许一个vtbl的存在,这样对于在编写COM组件时,是绝对必要的,他保证对函数的访问不会因为其他的干扰而导致在地址上的访问出错,尤其实在偏移量上(由对象在内存上的布置确定)。
另外,让destructor成为pure virtual绝对是个错误,你可以去掉base中的destructor试试,你运行会发现derived中的destructor不会被调用(换句话说,尽管base仍然使用了一个无操作的默认的destructor,但是,由于pure virtual的关系,你的derived class的destructor无法压抑)。
的确,很多人通过这样简单的测试得到一些不确切的结果,如果涉及多层次体系的话,任何一个virtual destructor的定义空白,会导致整个继承体系的virtual destructor调用失败。

如有不对,请指正!
chinajiji 2003-01-13
  • 打赏
  • 举报
回复
ckacka(小红帽):
你提及的"只在虚基类里面放入操作"我同意!因为纯虚基类就是一个接口,接口不要包含数据当然是正确的.我这里只是想说明一个语法问题,所以没有考虑设计上的问题.
你提及的"让destructor成为pure virtual绝对是个错误",我没有看没白,我也不认为这是一个错误,不论是语法上,还是设计上.
你说的:"如果涉及多层次体系的话,任何一个virtual destructor的定义空白,会导致整个继承体系的virtual destructor调用失败。"
我还是不明白,请说具体一点好吗?
ckacka 2003-01-13
  • 打赏
  • 举报
回复
详细一点:
如果去掉Base::~Base() { cout << "~Base()" << endl; }就是编译没有问题,而连接会出现错误!
如果同时去掉Base::~Base() { cout << "~Base()" << endl; }和virtual ~Base() = 0;就是编译连接都没有问题,但是~Derived() { cout << "~Derived()!" << endl; }的调用无法实现。
eion 2003-01-10
  • 打赏
  • 举报
回复
我想是在析构函数前加了 static 吧?
ckacka 2003-01-10
  • 打赏
  • 举报
回复
哦?
那我孤陋寡闻了,呵呵,不好意思。

不过我确实还没有见过抽象类里面斜构造函数的。
chinajiji 2003-01-10
  • 打赏
  • 举报
回复
ckacka(小红帽);
你好!我的程序哪里有问题哟?
请指教(:
ckacka 2003-01-10
  • 打赏
  • 举报
回复
你好,chinajiji(菜鸟叽叽) :
我们碰面了:)
很高兴和你在同一个公司!

另外,你的代码有问题的,建议你看看《深度探索 C++ 对象模型》的第五章!

给未来的同事问好了!
chinajiji 2003-01-10
  • 打赏
  • 举报
回复
小红帽,你好! 我来给你一个例子:

#include <iostream>
#include <stdlib.h>
using namespace std;

class Base {
public:
Base(int i) : m_i(i) { cout << "Base()" << endl; }
virtual ~Base() = 0;
private:
int m_i;
};

Base::~Base() { cout << "~Base()" << endl; }

class Derived : public Base {
public:
Derived(int i) : Base(i) { cout << "Derived()" << endl; }
~Derived() { cout << "~Derived()!" << endl; }
};

int main(int argc, char *argv[])
{
//! Base b(10); //Base 为纯虚类,这里将出错.
Base *pBase = new Derived(10);
delete pBase;
system("PAUSE");
return 0;
}
//输出结果:
/*
Base()
Derived()
~Derived()!
~Base()
请按任意键继续 . . .
*/
cenlmmx 2003-01-09
  • 打赏
  • 举报
回复
抽象类里面可以有构造函数
ckacka 2003-01-09
  • 打赏
  • 举报
回复
好像把构造函数和析构函数都申明为纯虚函数也可以!
ckacka 2003-01-09
  • 打赏
  • 举报
回复
抽象类里面不应该有构造函数和析构函数,因为抽象类根本就不会被实例化。

你把抽象类的构造函数和析构函数去掉!
招RD和QA 2003-01-09
  • 打赏
  • 举报
回复
show your code
ITMSC 2003-01-09
  • 打赏
  • 举报
回复
给出程序好吗?

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧