C++之保护和私有构造函数与析构函数

一、构造函数

1、保护

构造函数定义为protected后,就意味着你不能在类的外部构造对象了,而只能在外部构造该类的子类的对象,比如:

class Base

{

protected:

Base() {}

...

};

class Derived : public Base

{

public:

Derived() {}

...

};

Base b; //error

Derived d; //ok

2、私有

构造函数定义为private后,意味着不仅仅不能在类的外部构造对象了,而且也不能在外部构造该类的子类的对象了,只能通过类的static静态函数来访问类的内部定义的对象,单件singleton模式就是私有构造函数的典型实例:

class CLog

{

private:

CLog() {};

public:

~CLog() {};

public:

static CLog* GetInstance()

{

if (NULL == m_sopLogInstance)

{

CLock oInstanceLock;

oInstanceLock.Lock();

if (NULL == m_sopLogInstance)

{

m_sopLogInstance = new CLog();

}

oInstanceLock.Unlock();

}

return m_sopLogInstance;

}

...

private:

static CLog *m_sopLogInstance;

...

};

CLog &log = CLog::GetInstance();

3、拷贝构造和赋值操作符

拷贝构造和赋值操作符定义为私有后,意味着禁止在外部对类的对象进行复制操作。这种情况的典型应用是类的成员中含有锁成员变量时,禁止拷贝构造和赋值操作可以防止对象被拷贝后,拷贝的对象进行加锁后影响到原有对象加锁,从而违背码农意愿。

二、析构函数

对于堆中的对象,通常都是用new/delete来创建/销毁,当调用new时,它会自动调用相应类的构造函数,当调用delete时,它会自动调用相应类的析构函数。而在栈中产生对象时,对象的创建/销毁是自动完成的,也就是在创建时自动调用构造函数,在销毁时自动调用析构函数,即不需要显示调用new/delete,但有个前提是类的构造/析构函数都必须是public的。

析构函数无论是protected还是priavte,其共同作用都是禁止在栈中产生对象,因为无法自动完成析构函数的调用,自然就不能在栈中创建对象了;当然如果在堆上创建对象时,也不能直接delete对象了,因为这样也会在外部析构该对象,但是可以间接完成堆对象的析构,比如:

class Base

{

public:

Base() {}

private:

~Base() {}

public:

void Destroy() {delete this;}

};

为拥有私有或保护析构函数的类创建一个公有的Destroy函数来销毁对象即可。

那私有和保护析构函数有什么区别呢?区别在于私有的析构函数不仅禁止了栈中产生对象,而且同时也禁止了继承,下手也忒狠了了点,如果你不想太狠而不想限制继承,那就用保护的析构函数吧。

C++之保护和私有构造函数与析构函数

时间: 2024-11-25 08:28:30

C++之保护和私有构造函数与析构函数的相关文章

反射破坏单例的私有构造函数保护

Java的反射破坏单例的私有构造函数保护,最典型的就是Spring的Bean注入,我们可以通过改造私有构造函数来防止. 在Singleton中,我们只对外提供工厂方法(获取单例),而私有化构造函数,来防止外面多余的创建. 对于一般的外部调用来说,私有构造函数已经很安全了.        public class Singleton { private Singleton(){} private static volatile Singleton instance = null; public s

拷贝构造,深度拷贝,关于delete和default相关的操作,explicit,类赋初值,构造函数和析构函数,成员函数和内联函数,关于内存存储,默认参数,静态函数和普通函数,const函数,友元

 1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.第二种初始化的方式是直接在构造方法里面实现初始化. 案例如下: #include<iostream> //如果声明已经定义,边不会生成 class classA { private: int a; int b; public: //拷贝构造的规则,有两种方式实现初始化 //1.一个是通过在后面:a(x),b(y)的方式实现初始化 //2.第二种初始化的方式是直

C++文件头,命名空间,new和delete,内联函数,引用,函数重载,构造函数和析构函数,深拷贝和浅拷贝,explict,this指针

 目  录 1       开始学习C++.............................................................................................................. 4 1.1       C++的头文件.................................................................................................

C++ Primer 学习笔记_18_类与数据抽象(4)_构造函数、析构函数、explicit关键字、赋值与初始化、类成员的显式初始化

引言: 构造函数确保每个对象在创建时自动调用,以确保每个对象的数据成员都有合适的初始值. 一.构造函数.默认构造函数 1.构造函数 --构造函数是特殊的成员函数 --构造函数是为了保证对象的每个数据成员都被正确初始化 --函数名和类名完全相同 --不能定义构造函数的类型(返回类型),也不能使用void --通常情况下构造函数应声明为公有函数,一般被隐式地调用. --构造函数被声明为私有有特殊的用途,比如单例模式. (1).构造函数可以被重载 一般而言,不同的构造函数允许用户指定不同的方式来初始化

构造函数和析构函数的作用[转]

千万不要把构造函数和析构函数同普通的函数等同起来看待. 给你一段介绍,这个是一位真正的高手的回答,看了你就会明白的.第9章         类的构造函数.析构函数与赋值函数构造函数.析构函数与赋值函数是每个类最基本的函数.它们太普通以致让人容易麻痹大意,其实这些貌似简单的函数就象没有顶盖的下水道那样危险.         每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含一个拷贝构造函数,其它的称为普通构造函数).对于任意一个类A,如果不想编写上述函数,C++编译器将自动为A产生四

C++中构造函数或析构函数定义为private

转自:http://www.blogjava.net/fhtdy2004/archive/2009/05/30/278971.html 很多情况下要求当前的程序中只有一个object.例如一个程序只有一个和数据库的连接,只有一个鼠标的object.通常我们都将构造函数的声明置于public区段,假如我们将其放入private区段中会发生什么样的后果?这意味着什么? (1)构造函数定义private      当我们在程序中声明一个对象时,编译器为调用构造函数(如果有的话),而这个调用将通常是外部

【php】利用php的构造函数与析构函数编写Mysql数据库查询类 (转)

上次在<[php]利用原生态的JavaScript Ajax为php进行MVC分层设计,兼容IE6>(点击打开链接) 一文中,对于php查询Mysql数据库的model.php写法还不够完善,在每一个方法中还需要自己声明mysql的$con对象,同时自己关闭 mysql的$con对象.这样,如果查询方法一多,再无缘无故地增加了许多声明$con对象与关闭$con对象的代码.其实完全可以利用php的构造函 数与析构函数给数据库类各个查询方法的注入$con对象,同时自动在每次查询之后自动回收$con

私有构造函数(C# 编程指南)

私有构造函数是一种特殊的实例构造函数.它通常用在只包含静态成员的类中.如果类具有一个或多个私有构造函数而没有公共构造函数,则其他类(除嵌套类外)无法创建该类的实例.例如: C# class NLog { // Private Constructor: private NLog() { } public static double e = Math.E; //2.71828... } 声明空构造函数可阻止自动生成默认构造函数.注意,如果您不对构造函数使用访问修饰符,则在默认情况下它仍为私有构造函数

【ThinkingInC++】33、构造函数和析构函数的各种特征

/** * 书本:[ThinkingInC++] * 功能:构造函数和析构函数的各种特征 * 时间:2014年8月26日08:50:52 * 作者:cutter_point */ /* 构造函数和析构函数是没有返回值的. 析构函数:当对象超出他的作用域的时候,编译器将自动调用析构函数,但析构函数调用的 唯一证据是包含该对象的右括号,而且即使使用goto语句跳转析构函数任然被调用 */ #include<iostream> using namespace std; class Tree { in