基类的析构函数为保护的时候

combobox2013 2013-07-11 11:42:29
1. 基类的析构函数为保护的时候

为什么要这样设计呢? 不明白有什么意义?

而且delete 基类指针 从语法角度看, 会去调用 基类的析构函数, 此时会protected,

可以调用吗?


2.
构造函数,析构函数, 拷贝构造, 这3种都可以继承给 派生类吗?


...全文
276 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2013-07-22
  • 打赏
  • 举报
回复
create 做成虚函数,这相当于虚构造函数,这不是三言两语可以说清楚的。 真想这样做的话,搜一下虚构造函数这个话题,或者看一下 《Effective C++》,和《More Effective C++》这两本书,具体哪一本书记不住了,其中一本书里讨论了虚构造函数的话题。
lm_whales 2013-07-17
  • 打赏
  • 举报
回复
create 不用了吧,子类构造函数会,调用基类的构造函数的,不然在初始化表里,明确初始化基类对象即可,protected 就是干这个的,让子类继承的;
combobox2013 2013-07-12
  • 打赏
  • 举报
回复
引用 14 楼 zhaokai115 的回复:
[quote=引用 13 楼 combobox2013 的回复:] [quote=引用 12 楼 ri_aje 的回复:] [quote=引用 9 楼 combobox2013 的回复:] [quote=引用 8 楼 combobox2013 的回复:] [quote=引用 7 楼 ri_aje 的回复:] [quote=引用 4 楼 combobox2013 的回复:] [quote=引用 2 楼 ri_aje 的回复:] 1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承 [/quote] 不懂你说什么,为啥基类的复制构造函数无法使用,写点儿代码秀一下你的观点。[/quote] 我是按照你的回帖得出的结论啊: 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。 举个例子: [/quote] 例子: class A { ... public: A(const A& onther) { } }; class B: public A { public: B( const B& another) { } }; 调用: B obj1; B ojb2= obj1; //拷贝构造 如果A中有指针成员,A的拷贝构造代码里也做了深拷贝。 但是B的构造函数代码并没有对继承过来的指针成员做深拷贝, B的拷贝构造所做的工作仅仅是: 对B类新增加的数据成员做处理, A的成员它不管, B的拷贝构造只提供了处理B新增加的数据成员的代码, 那么此时 B obj2=obj1; 能否获得我们需要的正确结果呢? [/quote] 我说 "自定义复制构造函数的话,需要自己调用。" 是这个意思。

class B: public A
{
public:
B( const B& another) 
: A(another) // here, you have to explicitly call base class copy ctor.
{
}
};
[/quote] 原来如此,多谢 那10楼中提到的: 么是否可以说,我们的多态在使用的时候, 比如销毁你new出来的对象,就必须dynamic_cast为你的派生类,然后销毁。 对不? 感觉不对啊, 这样太麻烦了啊, 呵呵。 [/quote] 一般不推荐用dynamic_cast,可以定义一个虚函数,让派生类自己销毁。
class Base {
public:
    virtual void release() = 0;
};

class Derived: public Base {
private:
    virtual void release() { delete this; }
};
[/quote] 聪明, 不过我马上 发现个问题了: 你不觉得不对称吗? 有release ,没有 create什么的? 做个补充: 当基类的析构函数为protected的时候, 可以做以下几个处理: 1. 基类的构造函数,拷贝构造函数,均设置成 protected。 可以达到不能够直接new, delete一个基类的目的。 2. 基类依然需要提供一个create, release函数 ,而且是虚函数 3. 派生类 的构造,拷贝构造均需要搞成 private,通过create去 生成对象, release释放对象。
ri_aje 2013-07-11
  • 打赏
  • 举报
回复
引用 4 楼 combobox2013 的回复:
[quote=引用 2 楼 ri_aje 的回复:] 1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承 [/quote] 不懂你说什么,为啥基类的复制构造函数无法使用,写点儿代码秀一下你的观点。
www_adintr_com 2013-07-11
  • 打赏
  • 举报
回复
引用 3 楼 combobox2013 的回复:
[quote=引用 1 楼 adlay 的回复:] 1. 基于某种原因不想让你去 delete 基类指针吧. 比如它是一个单件的时候之类的. 2. 不会. 如果派生类没有提供自己的, 编译器会合成一个默认的.
你好,方便讨论下你说第一点吗? 我一般用单件,是派生了继承一个模板类, 就可以了。 此时确实不会 delete 基类指针 好了,居然你说,为protected的话,不可以调用, 只是让派生类去调用 基类的析构函数,达到销毁基类的目的。 我们完全可以将基类的析构 设置为private啊,呵呵 [/quote] 设置为 private 的话派生类也不能销毁了... 举个最简单的单件例子吧:

class B
{
protected:
	virtual ~B() {};

};

class D : public B
{
public:
	virtual ~D() {};
};

B* get_Sing()
{
	static D d;
	return &d;
}

int main()
{
	B* s = get_Sing();
	//delete s; // 出错, 被保护的
}
如果再把上面的 protected 改成 private, D 自己析构的时候都会出错, 注释掉 delete s 也编译不过.
平凡的闰土 2013-07-11
  • 打赏
  • 举报
回复
对于构造函数,如果基类需要参数的话那么派生类必须也要传递参数,也就是说,派生类需要为基类提供构造函数的参数,二对于析构函数则不用,每一层派生只需要对自己的资源进行回收就行,不用你去管基类的,基类自己的析构函数会回收其资源
combobox2013 2013-07-11
  • 打赏
  • 举报
回复
引用 2 楼 ri_aje 的回复:
1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承
combobox2013 2013-07-11
  • 打赏
  • 举报
回复
引用 1 楼 adlay 的回复:
1. 基于某种原因不想让你去 delete 基类指针吧. 比如它是一个单件的时候之类的. 2. 不会. 如果派生类没有提供自己的, 编译器会合成一个默认的.
你好,方便讨论下你说第一点吗? 我一般用单件,是派生了继承一个模板类, 就可以了。 此时确实不会 delete 基类指针 好了,居然你说,为protected的话,不可以调用, 只是让派生类去调用 基类的析构函数,达到销毁基类的目的。 我们完全可以将基类的析构 设置为private啊,呵呵
ri_aje 2013-07-11
  • 打赏
  • 举报
回复
1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
www_adintr_com 2013-07-11
  • 打赏
  • 举报
回复
1. 基于某种原因不想让你去 delete 基类指针吧. 比如它是一个单件的时候之类的. 2. 不会. 如果派生类没有提供自己的, 编译器会合成一个默认的.
ri_aje 2013-07-11
  • 打赏
  • 举报
回复
引用 13 楼 combobox2013 的回复:
[quote=引用 12 楼 ri_aje 的回复:] [quote=引用 9 楼 combobox2013 的回复:] [quote=引用 8 楼 combobox2013 的回复:] [quote=引用 7 楼 ri_aje 的回复:] [quote=引用 4 楼 combobox2013 的回复:] [quote=引用 2 楼 ri_aje 的回复:] 1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承 [/quote] 不懂你说什么,为啥基类的复制构造函数无法使用,写点儿代码秀一下你的观点。[/quote] 我是按照你的回帖得出的结论啊: 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。 举个例子: [/quote] 例子: class A { ... public: A(const A& onther) { } }; class B: public A { public: B( const B& another) { } }; 调用: B obj1; B ojb2= obj1; //拷贝构造 如果A中有指针成员,A的拷贝构造代码里也做了深拷贝。 但是B的构造函数代码并没有对继承过来的指针成员做深拷贝, B的拷贝构造所做的工作仅仅是: 对B类新增加的数据成员做处理, A的成员它不管, B的拷贝构造只提供了处理B新增加的数据成员的代码, 那么此时 B obj2=obj1; 能否获得我们需要的正确结果呢? [/quote] 我说 "自定义复制构造函数的话,需要自己调用。" 是这个意思。

class B: public A
{
public:
B( const B& another) 
: A(another) // here, you have to explicitly call base class copy ctor.
{
}
};
[/quote] 原来如此,多谢 那10楼中提到的: 么是否可以说,我们的多态在使用的时候, 比如销毁你new出来的对象,就必须dynamic_cast为你的派生类,然后销毁。 对不? 感觉不对啊, 这样太麻烦了啊, 呵呵。 [/quote] 因为你就不该这样用。
zhaokai115 2013-07-11
  • 打赏
  • 举报
回复
引用 13 楼 combobox2013 的回复:
[quote=引用 12 楼 ri_aje 的回复:] [quote=引用 9 楼 combobox2013 的回复:] [quote=引用 8 楼 combobox2013 的回复:] [quote=引用 7 楼 ri_aje 的回复:] [quote=引用 4 楼 combobox2013 的回复:] [quote=引用 2 楼 ri_aje 的回复:] 1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承 [/quote] 不懂你说什么,为啥基类的复制构造函数无法使用,写点儿代码秀一下你的观点。[/quote] 我是按照你的回帖得出的结论啊: 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。 举个例子: [/quote] 例子: class A { ... public: A(const A& onther) { } }; class B: public A { public: B( const B& another) { } }; 调用: B obj1; B ojb2= obj1; //拷贝构造 如果A中有指针成员,A的拷贝构造代码里也做了深拷贝。 但是B的构造函数代码并没有对继承过来的指针成员做深拷贝, B的拷贝构造所做的工作仅仅是: 对B类新增加的数据成员做处理, A的成员它不管, B的拷贝构造只提供了处理B新增加的数据成员的代码, 那么此时 B obj2=obj1; 能否获得我们需要的正确结果呢? [/quote] 我说 "自定义复制构造函数的话,需要自己调用。" 是这个意思。

class B: public A
{
public:
B( const B& another) 
: A(another) // here, you have to explicitly call base class copy ctor.
{
}
};
[/quote] 原来如此,多谢 那10楼中提到的: 么是否可以说,我们的多态在使用的时候, 比如销毁你new出来的对象,就必须dynamic_cast为你的派生类,然后销毁。 对不? 感觉不对啊, 这样太麻烦了啊, 呵呵。 [/quote] 一般不推荐用dynamic_cast,可以定义一个虚函数,让派生类自己销毁。
class Base {
public:
    virtual void release() = 0;
};

class Derived: public Base {
private:
    virtual void release() { delete this; }
};
combobox2013 2013-07-11
  • 打赏
  • 举报
回复
引用 12 楼 ri_aje 的回复:
[quote=引用 9 楼 combobox2013 的回复:] [quote=引用 8 楼 combobox2013 的回复:] [quote=引用 7 楼 ri_aje 的回复:] [quote=引用 4 楼 combobox2013 的回复:] [quote=引用 2 楼 ri_aje 的回复:] 1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承 [/quote] 不懂你说什么,为啥基类的复制构造函数无法使用,写点儿代码秀一下你的观点。[/quote] 我是按照你的回帖得出的结论啊: 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。 举个例子: [/quote] 例子: class A { ... public: A(const A& onther) { } }; class B: public A { public: B( const B& another) { } }; 调用: B obj1; B ojb2= obj1; //拷贝构造 如果A中有指针成员,A的拷贝构造代码里也做了深拷贝。 但是B的构造函数代码并没有对继承过来的指针成员做深拷贝, B的拷贝构造所做的工作仅仅是: 对B类新增加的数据成员做处理, A的成员它不管, B的拷贝构造只提供了处理B新增加的数据成员的代码, 那么此时 B obj2=obj1; 能否获得我们需要的正确结果呢? [/quote] 我说 "自定义复制构造函数的话,需要自己调用。" 是这个意思。

class B: public A
{
public:
B( const B& another) 
: A(another) // here, you have to explicitly call base class copy ctor.
{
}
};
[/quote] 原来如此,多谢 那10楼中提到的: 么是否可以说,我们的多态在使用的时候, 比如销毁你new出来的对象,就必须dynamic_cast为你的派生类,然后销毁。 对不? 感觉不对啊, 这样太麻烦了啊, 呵呵。
ri_aje 2013-07-11
  • 打赏
  • 举报
回复
引用 9 楼 combobox2013 的回复:
[quote=引用 8 楼 combobox2013 的回复:] [quote=引用 7 楼 ri_aje 的回复:] [quote=引用 4 楼 combobox2013 的回复:] [quote=引用 2 楼 ri_aje 的回复:] 1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承 [/quote] 不懂你说什么,为啥基类的复制构造函数无法使用,写点儿代码秀一下你的观点。[/quote] 我是按照你的回帖得出的结论啊: 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。 举个例子: [/quote] 例子: class A { ... public: A(const A& onther) { } }; class B: public A { public: B( const B& another) { } }; 调用: B obj1; B ojb2= obj1; //拷贝构造 如果A中有指针成员,A的拷贝构造代码里也做了深拷贝。 但是B的构造函数代码并没有对继承过来的指针成员做深拷贝, B的拷贝构造所做的工作仅仅是: 对B类新增加的数据成员做处理, A的成员它不管, B的拷贝构造只提供了处理B新增加的数据成员的代码, 那么此时 B obj2=obj1; 能否获得我们需要的正确结果呢? [/quote] 我说 "自定义复制构造函数的话,需要自己调用。" 是这个意思。

class B: public A
{
public:
B( const B& another) 
: A(another) // here, you have to explicitly call base class copy ctor.
{
}
};
www_adintr_com 2013-07-11
  • 打赏
  • 举报
回复
引用 10 楼 combobox2013 的回复:
[quote=引用 6 楼 adlay 的回复:] [quote=引用 3 楼 combobox2013 的回复:] [quote=引用 1 楼 adlay 的回复:] 1. 基于某种原因不想让你去 delete 基类指针吧. 比如它是一个单件的时候之类的. 2. 不会. 如果派生类没有提供自己的, 编译器会合成一个默认的.
你好,方便讨论下你说第一点吗? 我一般用单件,是派生了继承一个模板类, 就可以了。 此时确实不会 delete 基类指针 好了,居然你说,为protected的话,不可以调用, 只是让派生类去调用 基类的析构函数,达到销毁基类的目的。 我们完全可以将基类的析构 设置为private啊,呵呵 [/quote] 设置为 private 的话派生类也不能销毁了... 举个最简单的单件例子吧:

class B
{
protected:
	virtual ~B() {};

};

class D : public B
{
public:
	virtual ~D() {};
};

B* get_Sing()
{
	static D d;
	return &d;
}

int main()
{
	B* s = get_Sing();
	//delete s; // 出错, 被保护的
}
如果再把上面的 protected 改成 private, D 自己析构的时候都会出错, 注释掉 delete s 也编译不过.[/quote] 你好,你的问题我做了一个引申, 如果基类指针不能被delete ,因为是protected了, 那么是否可以说,我们的多态在使用的时候, 比如销毁你new出来的对象,就必须dynamic_cast为你的派生类,然后销毁。 [/quote] 如果基类的析构 protected 了, 确实是这样.
combobox2013 2013-07-11
  • 打赏
  • 举报
回复
引用 6 楼 adlay 的回复:
[quote=引用 3 楼 combobox2013 的回复:] [quote=引用 1 楼 adlay 的回复:] 1. 基于某种原因不想让你去 delete 基类指针吧. 比如它是一个单件的时候之类的. 2. 不会. 如果派生类没有提供自己的, 编译器会合成一个默认的.
你好,方便讨论下你说第一点吗? 我一般用单件,是派生了继承一个模板类, 就可以了。 此时确实不会 delete 基类指针 好了,居然你说,为protected的话,不可以调用, 只是让派生类去调用 基类的析构函数,达到销毁基类的目的。 我们完全可以将基类的析构 设置为private啊,呵呵 [/quote] 设置为 private 的话派生类也不能销毁了... 举个最简单的单件例子吧:

class B
{
protected:
	virtual ~B() {};

};

class D : public B
{
public:
	virtual ~D() {};
};

B* get_Sing()
{
	static D d;
	return &d;
}

int main()
{
	B* s = get_Sing();
	//delete s; // 出错, 被保护的
}
如果再把上面的 protected 改成 private, D 自己析构的时候都会出错, 注释掉 delete s 也编译不过.[/quote] 你好,你的问题我做了一个引申, 如果基类指针不能被delete ,因为是protected了, 那么是否可以说,我们的多态在使用的时候, 比如销毁你new出来的对象,就必须dynamic_cast为你的派生类,然后销毁。
combobox2013 2013-07-11
  • 打赏
  • 举报
回复
引用 8 楼 combobox2013 的回复:
[quote=引用 7 楼 ri_aje 的回复:] [quote=引用 4 楼 combobox2013 的回复:] [quote=引用 2 楼 ri_aje 的回复:] 1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承 [/quote] 不懂你说什么,为啥基类的复制构造函数无法使用,写点儿代码秀一下你的观点。[/quote] 我是按照你的回帖得出的结论啊: 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。 举个例子: [/quote] 例子: class A { ... public: A(const A& onther) { } }; class B: public A { public: B( const B& another) { } }; 调用: B obj1; B ojb2= obj1; //拷贝构造 如果A中有指针成员,A的拷贝构造代码里也做了深拷贝。 但是B的构造函数代码并没有对继承过来的指针成员做深拷贝, B的拷贝构造所做的工作仅仅是: 对B类新增加的数据成员做处理, A的成员它不管, B的拷贝构造只提供了处理B新增加的数据成员的代码, 那么此时 B obj2=obj1; 能否获得我们需要的正确结果呢?
combobox2013 2013-07-11
  • 打赏
  • 举报
回复
引用 7 楼 ri_aje 的回复:
[quote=引用 4 楼 combobox2013 的回复:] [quote=引用 2 楼 ri_aje 的回复:] 1. 一般用来禁止生成基类对象,强制通过派生类使用基类功能,NVI pattern 就用了这招儿。 2. 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。
自定义复制构造函数的话,需要自己调用。 这么说, 派生类的拷贝构造函数,我们也要提供 对基类的拷贝了, 因为基类的拷贝构造函数,已经无法使用了, 派生类不能使用,所谓的不能继承 [/quote] 不懂你说什么,为啥基类的复制构造函数无法使用,写点儿代码秀一下你的观点。[/quote] 我是按照你的回帖得出的结论啊: 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。 举个例子:

65,184

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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