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



 

目 

1      
开始学习C++..............................................................................................................
4

1.1      
C++的头文件.......................................................................................................
4

1.2      
命名空间...............................................................................................................
4

1.3      
更严格的类型转化................................................................................................
4

1.4      
new和delete.......................................................................................................
4

1.5      
内联函数...............................................................................................................
4

1.6      
引用......................................................................................................................
5

1.7      
函数的重载...........................................................................................................
5

2      
类和对象......................................................................................................................
6

2.1      
C++类成员
的保护
..............................................................................................
6

2.2      
C++类的本质.......................................................................................................
6

2.3      
类的作用域...........................................................................................................
6

2.4      
类的构造和析构函数............................................................................................
6

2.5      
构造函数的初始化成员列表.................................................................................
6

2.5.1       
原则:...........................................................................................................
7

2.6      
拷贝构造函数.......................................................................................................
7

2.6.1       
浅拷贝...........................................................................................................
7

2.6.2       
深拷贝...........................................................................................................
7

2.6.3       
原则:...........................................................................................................
8

2.7      
常量类成员,常量对象。.....................................................................................
8

2.8      
explicit.................................................................................................................
8

2.9      
this指针...............................................................................................................
8

2.10   
类的static成员变量............................................................................................
8

1         开始学习C++

 

1.1      
C++
的头文件

传统的C头文件。(支持.h头文件,比如:#include<stdio.h>)

C++头文件。(不加.h的头文件,比如:#include<iostream>)

hpp文件件。(支持.hpp头文件)

在工作中如果有C的也有C++的,最好使用带有.h的头文件

1.2      操作符重载

cout << "Hello World!"<< endl;

这里的”<<”实际上进行了操作符的重载。

1.3      关于使用命名空间的情况

A:使用类似:using
namespace std;

B:如果不使用用usingnamespace
std;那么这个时候可以在代码中使用类似下面的情况:

std:cout << "Helloworld\n" << endl;

1.4      
命名空间

C++引入了新的概念,命名空间可以有效避免大型项目中的各种名称冲突

class关键字

class是C++的核心,是面向对象编程的核心内容。一个class案例:

#include <iostream>

#include <string.h>

using namespace std;

 

class man{

public://共有的

   char name[100];

 

private://私有的,只要下面不访问这里的age,程序就不会出现问题

   int age;

 

public:

   int sex;

};  //注意:这里最后要有一个分号

 

int main()

{

   man m;

   strcpy(m.name,"tom");

   m.sex = 1;

   cout << m.name << m.sex << endl;

 

   return 0;

}

自定义命名空间:

使用匿名命名空间:

 

namespace
{

   
void
func()

 
  {

       
cout
<< "demo2
func" <<
endl2;

 }

}

 

1.5      volatile关键字

通过volatile关键字使代码不被编译器优化,案例:

volatile int i=0;//保证i不被编译器优化,以便能进行中间步骤

i+=6;

i+=7;

如果加了volatile关键字,那么就使程序不被优化成为

i+=13

1.6      
更严格的类型转化

在C++,不同类型的指针是不能直接赋值的,必须强转。(也就是如果两个指针类型不同,不能直接把一个赋值给另外一个,而是要通过强转的方式实现)

1.7      
new
和delete

c++中不建议使用malloc和free开辟内存或释放内存。而是使用new和delete。

new和delete是C++内建的操作符,不需要有任何头文件,用new分配的内存必须用delete释放,不要用free。

int *p=new int;           
等价于:int*p=new int(10);//分配内存的同时初始化

*p =10;                         
delete p;

delete p;

p = NULL;

 

new创建数组的方法new[];

int *p=new int[10];  
//表示开辟10个空间的数组

for(int i=0;i<10;i++)

{

p[i]=i;

}

//输出结果

for(int i = 0;i<10;i++)

{

   cout << p[i] << endl;

}

delete []p; //如果要删除这些数组的空间,要加上[],表示这时候删除的是一个数组。

P = NULL;

1.8      
内联函数

inline关键字的意思是,内联函数不作为函数调用,而是直接把内联函数的代码嵌

入到调用的语句中

内联函数适合函数代码很少,并且有频繁的大量调用。

1.9      
引用

引用就是一个变量的别名,比如

int a = 5;

int &c = a;  
//这里的c就相当于是a的别名

引用不是地址,虽然加上了&。

函数的缺省参数

C++允许函数在定义的时候,提供缺省参数,如果调用函数的时候没有提供形参,那么形参的值就是缺省值,也就是说用默认值。

#include
<iostream>

#include
<stdio.h>

#include
<stdlib.h>

#include
<string.h>

 

using
namespace
std;

 

void
func(int
a
=
10)

{

   
printf("a
=
%d",a);

}

   

int
main()

{

   
   func();  
//这时候没有填写参数

   
   return
0;

}

上面代码运行的结果是10.

 

此外,函数会自动通过传递的参数类匹配调用哪个函数,案例如下:

引用做为函数的参数,没有出栈,入栈的操作,所以效率更高

如果要使引用参数的值不能在函数内部被修改,那么就定义为常量引用 const &

引用例子:

 

1.10 
函数的重载

函数的名称是一样的,但参数不同可以重载

函数参数相同,但返回值不同,不可以重载

1.11 模板

A:模板的概念

我们已经学过重载(Overloading),对重载函数而言,C++的检查机制能通过函数参数的不同及所属类的不同。正确的调用重载函数。例如,为求两个数的最大值,我们定义MAX()函数需要对不同的数据类型分别定义不同重载(Overload)版本。

//函数1.

int max(int x,int y);
{return(x>y)?x:y ;}

//函数2.
float max( float x,float y){
return (x>y)? x:y ;}

//函数3.
double max(double x,double y)
{return (c>y)? x:y ;}

但如果在主函数中,我们分别定义了 chara,b;
那么在执行max(a,b);时
程序就会出错,因为我们没有定义char类型的重载版本。

现在,我们再重新审视上述的max()函数,它们都具有同样的功能,即求两个数的最大值,能否只写一套代码解决这个问题呢?这样就会避免因重载函数定义不
全面而带来的调用错误。为解决上述问题C++引入模板机制,模板定义:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数,
从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。

   
B:函数模板的写法

函数模板的一般形式如下:

Template <class或者也可以用typename
T>

返回类型
函数名(形参表)
{//
函数定义体
}

说明: template是一个声明模板的关键字,表示声明一个模板关键字class不能省略,如果类型形参多余一个
,每个形参前都要加class <类型
形参表>可以包含基本数据类型可以包含类类型.

请看以下程序:

//Test.cpp

#include
<iostream>

using std::cout;

using std::endl;

//声明一个函数模版,用来比较输入的两个相同数据类型的参数的大小,class也可以被typename代替,

//T可以被任何字母或者数字代替。

template <class
T>

T min(T x,T y)

{
return(x<y)?x:y;}

void main( )

{

    
intn1=2,n2=10;

    
doubled1=1.5,d2=5.6;

     cout<<
"较小整数:"<<min(n1,n2)<<endl;

     cout<<
"较小实数:"<<min(d1,d2)<<endl;

     system("PAUSE");

}

程序运行结果:

程序分析:main()函数中定义了两个整型变量n1
, n2 两个双精度类型变量d1 , d2然后调用min(
n1,n2); 即实例化函数模板T min(Tx, T y)其中T为int型,求出n1,n2中的最小值.同理调用min(d1,d2)时,求出d1,d2中的最小值.

C:类模板的写法

定义一个类模板:

Template < class或者也可以用typename
T >

class
类名{
//类定义......
};

说明:其中,template是声明各模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个。

例如:定义一个类模板:

// ClassTemplate.h
#ifndef ClassTemplate_HH

#define ClassTemplate_HH

template<typename
T1,typename T2>

class myClass{

private:

     T1 I;

     T2 J;

public:

     myClass(T1 a, T2 b);//Constructor

    
void show();

};

//这是构造函数

//注意这些格式

template <typename
T1,typename T2>

myClass<T1,T2>::myClass(T1 a,T2 b):I(a),J(b){}

//这是voidshow();

template <typename
T1,typename T2>

void myClass<T1,T2>::show()

{

     cout<<"I="<<I<<",J="<<J<<endl;

}

#endif

// Test.cpp

#include
<iostream>

#include
"ClassTemplate.h"

using std::cout;

using std::endl;

void main()

{

     myClass<int,int>class1(3,5);

     class1.show();

     myClass<int,char>class2(3,'a');

     class2.show();

     myClass<double,int>class3(2.9,10);

     class3.show();

     system("PAUSE");

}

最后结果显示:

 

2         类和对象

2.1      
C++
类成员的保护

如果类函数返回的是成员变量的指针,为了避免在类外部成员变量被修改,所以函数就要返回常量指针

#include
<iostream>

#include
<stdio.h>

#include
<stdlib.h>

#include
<string.h>

 

using
namespace
std;

 

class
man{

private:

   
char
name[100];

   
int
age;

 

public: 
//共有方法

   
void
set_name(const
char
*s)

   
{

       
memset(name,0,sizeof(name));

       
if(strcmp(s,"tom")
==
0)

           
return;

       
strcpy(name,s);

   
}

   
void
set_age(int
i)

   
{

       
age
=
i;

   
}

   
char
*get_name()

   
{

       
return
name;

   
}

   
int
get_age()

   
{

       
return
age;

   
}

};

 

int
main()

{

   
man
m;

   
m.set_name("Marry");

   
//如果非想name改成tom,可以使用下面的方式

   
char
*p
=
m.get_name();

   
strcpy(p,"tom");

   

   
cout
<< m.get_name()
<< endl;

   
return
0;

}

如果一个类成员变量和一个全局变量重名,那么在类成员函数当中默认访问的是类的成员变量.

在类的内部访问全局标识,使用关键字::,表示释放全局变量或者全局函数

 

2.2      
C++
类的本质

类其实就是结构的数据成员加可执行代码,统一提供封装,继承,多态。

在类内部,没有权限限定符,默认是private

在结构内部,没有权限限定符,默认是public

一个类的案例:

编写头文件:

#ifndef
TEST_H

#define
TEST_H

 

class
man

{

private:

   
char
name[100];

   
int
age;

public:

   
man();

   
void
set_name(const
char
*s);

   
void
set_age(int
i);

   
const
char
*get_name();

   
int
get_age();

//   
int
get_age()
//很有可能被编译器编译为inline了

//   
{

//       
return
age;

//   
}

};

 

#endif
//
TEST_H

编写头文件的实现代码如下:

#include
"test.h"

#include
<string.h>

 

man::man()

{}

 

void
man::set_name(const
char
*s)

{

   
strcpy(name,s);

}

 

void
man::set_age(int
i)

{

   
age
=
i;

}

 

const
char
*man::get_name()

{

   
return
name;

}

 

int
man::get_age()

{

   
return
age;

}

类的调用的简单案例:

#include
<iostream>

#include
<stdio.h>

#include
<stdlib.h>

#include
<string.h>

#include
"test.h"

 

using
namespace
std;

 

int
main()

{

   
man
m;

   
m.set_name("Marry");

   
m.set_age(20);

 

   
//类的大小实际上是成员变量的大小,和去掉方法后的结构体的大小时相同的

   
printf("sizeof(man)
=
%d\n",sizeof(man));

 

   
cout
<< m.get_name()
<< endl;

   
cout
<< m.get_age()
<< endl;

 

   
return
0;

}

2.3      
类的作用域

类成成员变量作用域局限于类内部,类的外部是不可见。

一般不要在头文件里面定义变量。否则会出现问题。

2.4      
类的构造和析构函数

构造函数名称和类的名称一致,而且没有返回值,在一个类实例化为一个对象的时候,自动调用。

如果没有写构造函数,会生成一个默认的构造函数和析构函数,这时候编译器会自动生成。

一个对象在销毁的时候会自动调用析构函数。

 

如果想传递给函数一个类的变量,为了内存消耗减小,传递的是一个类的指针。或引用

2.5      
构造函数的初始化成员列表

初始化成员列表只能在构造函数使用

const成员必须用初始化成员列表赋值

引用数据成员必须用初始化成员列表赋值

案例:

编写头文件:

#ifndef
TEST_H

#define
TEST_H

 

class
man

{

private:

   
char
name[100];

   
const
int
age; 
//如果是一个常量,必须是通过初始化常量列表的方式赋值,也就是说通过:方式赋值

   
//如果这里写上man和~man,这时候会出现错误。

public:

   
man();//构造函数的作用是初始化参数值

   
//重载构造函数

   
man(const
char
*);

   
man(const
char
*s,int
i);

   
~man();

   
void
set_name(const
char
*s);

   
void
set_age(int
i);

   
const
char
*get_name();

   
int
get_age();

   
void
test();

//   
int
get_age()
//很有可能被编译器编译为inline了

//   
{

//       
return
age;

//   
}

};

 

#endif
//
TEST_H

 

 

编写实现的代码:

#include
"test.h"

#include
<string.h>

#include
<iostream>

 

using
namespace
std;

 

//构造函数,在对象被实例化的时候调用

man::man():age(24)  
//通过后面加上:的方式初始化成员变量的值

{

   
cout
<< "man"
<< endl;

   
//初始化name的值

   
memset(name,0,sizeof(name));

}

 

//构造函数的重载

man::man(const
char
*s):age(14)

{

   
strcpy(name,s);

}

 

//之所以在后面初始化值,是因为类的成员变量加了const了。

man::man(const
char
*s,
int
i):age(15)

{

   
cout
<< "man(const
char *s,
int i)
diao yong
le" <<
endl;

 

   
//动态分配内存,也是通过new的方式实现

 

   
//通过这种方式给成员变量赋值

   
strcpy(name,s);

}

 

man::~man()

{

   
//要想清楚在构造函数里分配的内存,需要在这里释放内存

   
//由于构造函数里只有一个,所以在不同的构造函数里面给函数成员指针分配内存的时候,一定

   
//要统一new或者new

   
cout
<< "~man"
<< endl;

}

 

void
man::set_name(const
char
*s)

{

   
strcpy(name,s);

}

 

void
man::set_age(int
i)

{

   
//age
=
i;

}

 

const
char
*man::get_name()

{

   
return
name;

}

 

int
man::get_age()

{

   
return
age;

}

 

void
man::test()

{

 

   
man
m; 
//在栈当中将man这个类实例化为一个对象叫man

   
m.set_name("toto");

   
cout
<< m.get_age()
<< endl;

   
cout
<< m.get_name()
<< endl;

 

   
//cout
<<
"----重载构造函数后的参数(1个参数)----"
<<
endl;

   
cout
<< "--one
argumemts--"
<< endl;

   
//有参构造的调用

   
man
m2("hello");

   
m.set_name("toto2");

   
cout
<< m2.get_age()
<< endl;

   
cout
<< m2.get_name()
<< endl;

 

   
//cout
<<
"----重载构造函数后的参数(2个参数)----"
<<
endl;

   
cout
<< "----two
arguments----"
<< endl;

   
//有参构造的调用

   
man
m3("hello",20);

   
m3.set_name("toto3");

   
cout
<< m3.get_age()
<< endl;

   
cout
<< m3.get_name()
<< endl;

}

 

编写main函数:

#include
<iostream>

#include
<stdio.h>

#include
<stdlib.h>

#include
<string.h>

#include
"test.h"

 

using
namespace
std;

 

int
main()

{

   
man
m;

   
m.test();

 

   
//调用没有参数的构造函数,在堆实例化一个对象

   
man
*p
=
new
man();

   
//要写下面一句,避免出现内存泄露!!

   
delete
p;   
//不能通过free(*p2)的方式使用

   
p
=
NULL;

 

   
man
*p2
=
new
man("hello",100);

   
delete
p2;  
//不能通过free(*p2)的方式使用

   
p2
=
NULL;

   
return
0;

}

 

2.5.1         原则:

由于析构函数只有一个,所以在不同的构造函数里面给函数的成员指针分配内存的时候,一定要统一new或者new[]

2.6      
拷贝构造函数

2.6.1         浅拷贝

两个对象之间成员变量简单的赋值。

比如:

man m1;

man m2 = m1;

2.6.2         深拷贝

不同的对象指针成员指向不同的内存地址,拷贝构造的时候不是简单的指针赋值,而是将内存拷贝过来(先申请内存空间)。

 

2.6.3         原则:

如果类成员有指针,那么需要自己实现拷贝构造函数,不然存在浅拷贝的风险。

2.7      
常量类成员,常量对象

类成员后面跟关键字const意思是告诉编译器,这个函数内部不会对类成员变量做任何修改。

 

函数的参数如果是一个类,那么就用类的引用。如果不想参数被调用函数内部修改,那么就采用const&

2.8      对象数组

#include
<iostream>

 

using
namespace
std;

 

class
demo

{

public:

   
demo()

   
{

       
cout
<< "demo"
<< endl;

   
}

   
demo(int
i)

   
{

       
cout
<< "demo
int" <<
i <<
endl;

   
}

   
~demo()

   
{

       
cout
<< "~demo"
<< endl;

   
}

};

 

int
main()

{

   
//定义对象数组,同时调用带有参数的构造函数

   
demo
d[3]
=
{demo(1),demo(2),demo(3)};

   
cout
<< "Hello
World!"
<< endl;

   
return
0;

}

 

2.9      
explicit

告诉C++编译器,要明确的调用这个构造函数,而不要自作聪明的认为=操作符是要调用构造的。

案例:

头文件:

#ifndef
MAN_H

#define
MAN_H

 

class
man

{

public:

   
char
*name;

   
int
age;

 

   
static
int
count;//定义一个类的静态成员变量,不可以进行初始化

 

public:

   
man();

   
explicit
man(int
age);//加了explicit之后表示就用这个构造函数。

   
man(const
man
&it);

   
man(const
char
*s,
int i
= 0);

   
~man();

   
void
set_name(const
char
*s);

   
void
set_age(int
i);

   
const
char
*get_name()
const;

   
int
get_age()
const;

   
man
*get_this();

   
static
void
set_count(int
i);

   
static
int
get_count();

};

 

#endif
//
MAN_H

 

实现类:

#include
<iostream>

#include
"man.h"

#include
<string.h>

 

using
namespace
std;

 

int
man::count
=
0;//类静态成员变量初始化的方式

 

man::man():age(0),
name(NULL)

{

   
cout
<< "man"
<< endl;

}

 

man::man(int
age)

{

   
cout
<< "man
int" <<
endl;

   
this->age
=
age;

}

 

man::man(const
man
&it)

{

   
cout
<< "copy
man" <<
endl;

   
name
=
new
char[100];

   
strcpy(name,
it.name);

   
age
=
it.age;

}

 

//man::man(const
char
*s)

//{

//   
strcpy(name,
s);

//}

 

//man::man(int
i)

//{

//
   age
=
i;

//}

 

man::man(const
char
*s,
int
i)

{

   
name
=
new
char[100];

   
cout
<< "man"
<< s
<< i
<< endl;

   
strcpy(name,
s);

   
age
=
i;

}

 

man::~man()

{

   
delete
[]name;

   
cout
<< "~man"
<< endl;

}

 

void
man::set_name(const
char
*s)

{

   
strcpy(name,
s);

}

 

void
man::set_age(int
i)

{

   
age
=
i;

}

 

const
char
*man::get_name()
const

{

   
return
name;

}

 

int
man::get_age()
const

{

   
return
age;

}

 

man
*man::get_this()

{

   
return
this;

}

 

void
man::set_count(int
i)

{

   
count
=
i;

   
//age
=
10;//类的静态函数内部不能直接访问类的动态成员变量。

}

 

int
man::get_count()

{

   
return
count;

}

 

main的代码

#include
<iostream>

#include
<stdio.h>

#include
<stdlib.h>

#include
<string.h>

#include
"man.h"

 

using
namespace
std;

 

void
test01()

{

   
man
m1("tom",
100);

   
man
m2
=
m1;//在栈当中将man这个类实例化为一个对象叫m

   
cout
<< "m2.name:"
<< m2.get_name()
<< endl;

   
m1.set_name("hello");

   
cout
<< "m2.name:"
<< m2.get_name()
<< endl;

}

 

void
test02(const
man
&m)

{

   
cout
<< m.get_name()
<< endl;

}

 

int
main()

{

   
//man::count
=
200;

   
man::set_count(200);

 

   
man
m;

   
printf("m
=
%p\n",
&m);

   
printf("%p\n",
m.get_this());

 

   
//m.set_count(500);

 

   
man
m1;

 

   
cout
<< m1.get_count()
<< endl;

   
return
0;

 

   
//cout
<<
"m1"
<<
m1.get_name()
<<
endl;

//   
man
*p
=
new
man("hello",
100);//调用没有参数的构造函数,在堆实例化一个对象

//   
delete
p;

 

   
return
0;

}

2.10 
this
指针

this就是指向自己实例的指针

字符串操作的案例:

头文件:

#ifndef
MYSTRING_H

#define
MYSTRING_H

 

#include
<iostream>

 

//一个单例的能够动态分配内存的字符串

class
mystring

{

private:

   
static
mystring
*self;

   
char
*s;

public:

   
static
mystring
*makestring(const
char
*s
= NULL);

   
static
void
deletestring();

 

   
~mystring();

   
const
char
*get_s()
const;

   
void
set_s(const
char
*s);

 

 

protected:

   
mystring();

   
mystring(const
char
*s);

   
mystring(const
mystring
&it);

 

};

 

#endif
//
MYSTRING_H

 

头文件的实现代码:

#include
"mystring.h"

#include
<iostream>

#include
<string.h>

 

mystring
*mystring::self
=
NULL;

 

mystring
*mystring::makestring(const
char
*s)

{

   
if
(self
==
NULL)

   
{

       
if
(s
==
NULL)

     
      self
=
new
mystring;

       
else

           
self
=
new
mystring(s);

   
}

 

   
return
self;

}

 

void
mystring::deletestring()

{

   
if
(self
!=
NULL)

   
{

       
delete
self;

       
self
=
NULL;//释放指针之后,赋值NULL,这样就可以再次建立类的实例

   
}

}

 

mystring::mystring():
s(NULL)

{

 

}

 

mystring::mystring(const
char
*s)

{

   
int
len
=
strlen(s);

   
this->s
=
new
char[len
+
1];

   
strcpy(this->s,
s);

   
this->s[len]
=
0;

}

 

mystring::mystring(const
mystring
&it)//通过拷贝构造实现深拷贝,避免成员变量指针赋值导致的错误

{

   
int
len
=
strlen(it.get_s());

   
this->s
=
new
char[len
+
1];

   
strcpy(this->s,
it.s);

   
this->s[len]
=
0;

}

 

mystring::~mystring()

{

   
delete
[]s;//将构造函数分配的内存释放

}

 

const
char
*mystring::get_s()
const

{

   
return
s;

}

 

void
mystring::set_s(const
char
*s)

{

   
if
(this->s
==
NULL)

   
{

       
int
len
=
strlen(s);

       
this->s
=
new
char[len
+
1];

       
strcpy(this->s,
s);

       
this->s[len]
=
0;

   
}else

   
{

       
int
len1
=
strlen(this->s);

       
int
len2
=
strlen(s);

 

       
if
(len1
>
len2)

   
    {

           
strcpy(this->s,
s);

           
this->s[strlen(s)]
=
0;

       
}else

       
{

           
delete
[]this->s;//由于成员变量s的空间不够了,所以不要了

           
this->s
=
new
char[len2
+
1];//重新给成员变量s分配新空间

           
strcpy(this->s,
s);//给新空间赋值

         
  this->s[len2]
=
0;//新空间最后一个字节为字符串结束标示符0

       
}

   
}

}

 

主函数的实现代码:

#include
<iostream>

#include
"mystring.h"

 

using
namespace
std;

 

int
main()

{

//   
mystring
str1("hello
world");

//   
mystring
str2
=
str1;

//   
str3.set_s("SDFSD");

//   
cout
<<
str1.get_s()
<<
endl;

   
//mystring
*str1
=
mystring::makestring();//默认调用的是NULL

 

   
mystring
*str1
=
mystring::makestring("hello
world");//默认调用的是NULL

 

   
cout
<< str1->get_s()
<< endl;

 

   
mystring::deletestring();

 

   
mystring
*str3
=
mystring::makestring("aaaaaaa");

 

   
cout
<< str3->get_s()
<< endl;

 

   
return
0;

}

 

2.11 
类的static
成员变量

static变量是放到静态内存区的,程序加载就存在,一直到程序退出才清理。

 

类的static成员和类的对象没有直接关系,类的静态成员是放到静态内存区的,程序开始执行就存在,一直到程序结束才清理。

类的静态成员变量不论类的实例有多少,但成员变量只有一份。

单例的一个案例:

编写头文件:

#ifndef
SINGLE_H

#define
SINGLE_H

 

class
single

{

private:

   
static
single
*p;

protected:

   
//构造函数被保护

   
single();

 

public:

   
//通过方法的方式实现生成实例

   
static
single
*makesignle();

   
static
void
releasesingle();

};

 

#endif
//
SINGLE_H

 

单例的实现代码:

#include
"single.h"

#include
<iostream>

 

single
*single::p
=
NULL;

 

single::single(){}

 

single
*single::makesignle()

{

   
if
(p
==
NULL)

       //如果p为空,就实例化对象返回,否则直接单例

       p
=
new
single;

   
return
p;

}

 

void
single::releasesingle()

{

   
delete
p;

   
p
=
NULL;

}

 

main实现类

#include
<iostream>

#include
"single.h"

 

using
namespace
std;

 

//实例化单例的例子

int
main()

{

   
single
*p
=
single::makesignle();

 

   
single
*p1
=
single::makesignle();

 

   
single::releasesingle();

   
cout
<< "Hello
World!"
<< endl;

   

   
return
0;

}

 

时间: 2025-01-20 20:05:49

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

【进阶】关于宏定义和内联函数

Tips: 1. 对于单纯常量,尽量用const对象或者enums替换 #define 2. 对于形似函数的宏(marcos),最好改用inline函数替换#define 我们先来看一般的宏定义 #define ASPECT_RATIO 1.653; 记号名称为ASPECT_RATIO也许从未被编译器看见: 也许在编译器开始处理源码之前它就被预处理器取走了.于是记号ASPECT_RATIO有可能没有进入到几号表(symbol table)内,于是当你运用此常量获得一个编译错误信息时,可能会带来困

C++如何处理内联虚函数

当一个函数是内联和虚函数时,会发生代码替换或使用虚表调用吗? 为了弄 清楚内联和虚函数,让我们将它们分开来考虑.通常,一个内联函数是被展开的 . class CFoo { private: int val; public: int GetVal() { return val; } int SetVal(int v) { return val=v; } }; 这里,如果使用下列代码: CFoo x; x.SetVal(17); int y = x.GetVal(); 那么编译器产生的目标代码将与下

OCP1z0-047 : 表连接――内联视图当作表使用

用sys用户登录,给oe用户授权dba,以便可以用oe用户查看执行计划: oe@OCM> conn / as sysdba Connected. sys@OCM> grant dba to oe; Grant succeeded. sys@OCM> conn oe/oe Connected. oe@OCM> set autot traceonly; oe@OCM> SELECT p.product_name,i.item_cnt 2 FROM (SELECT product_

C++标准编程:虚函数与内联

我们曾经在讨论C++的时候,经常会问到:"虚函数能被声明为内联吗?"现在,我们几乎听不到这个问题了.现在听到的是:"你不应该使print成为内联的.声明一个虚函数为内联是错误的!" 这种说法的两个主要的原因是(1)虚函数是在运行期决议而内联是一个编译期动作,所以,我们将虚函数声明为内联并得不到什么效果;(2)声明一个虚函数为内联导致了函数的多分拷贝,而且我们为一个不应该在任何时候内联的函数白白花费了存储空间.这样做很没脑子. 不过,事实并不是这样.我们先来看看第一个

C++ 内联inline

原文链接:http://www.cnblogs.com/berry/articles/1582702.html inline函数(摘自C++ Primer的第三版) 在函数声明或定义中函数返回类型前加上关键字inline即把函数指定为内联.       inline int min(int first, int secend) {/****/};       inline 函数对编译器而言必须是可见的,以便它能够在调用点内展开该函数.与非inline函数不同的是,inline函数必须在调用该函数

如何使用BBED查看SYSTEM文件头的root dba及bootstrap$

数据库版本11.2.0.4 实验思路是:     --其中数据库OPEN时的TRACE信息,可以参考:http://blog.csdn.net/q947817003/article/details/17025489 file#1 block#1==>root dba==>struct ktetb 即先从SYSTEM的数据文件头:file#1 block#1 找到root dba的位置,然后在root dba所在的块内,找到struct ktetb 所描述的块的位置,然后查看struct kte

拷贝构造,深度拷贝,关于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.第二种初始化的方式是直

转储控制文件头

控制       转出控制文件必须在数据库打开(OPEN)或者安装(MOUNT)的状态下进行.   1.      连接数据库 E:\>sqlplus "/ as sysdba"   SQL*Plus: Release 9.2.0.1.0 - Production on 星期五 5月 14 08:52:03 2004   Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.   连接到: Oracl

php通过文件头检测文件类型通用代码类(zip,rar等)

有时候我们这样做还不完善.可能有些人上存一些文件,但是他通过修改扩展名,让在我们的文件类型之内. 单实际访问时候又不能展示(因为扩展名与文件内容不符).下面这个php类,可能能够给我们带来帮助.一.php检测类 首先说明下,上面文件头与文件类型映射关系来自网上,如果你有新的文件需要检查,只需要将映射加入即可. 如果你需要知道文件头信息,可以通过工具:winhex打开标准文件查找.如: 代码: 复制代码 代码如下: <?php /*通过文件名,获得文件类型* *@author chengmo* *