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

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

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

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

可以调用吗?


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


...全文
271 18 打赏 收藏 转发到动态 举报
写回复
用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] 我是按照你的回帖得出的结论啊: 标准要求派生类构造函数和析构函数调用基类的。自定义复制构造函数的话,需要自己调用。 举个例子:

64,439

社区成员

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

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