包含:
http://www.cnblogs.com/uniqueliu/archive/2011/08/01/2124261.html
object.func().func2();
class A
{
//...
};
class B
{
//...
A a;
A b;
};
#include <iostream>
using namespace std;
class A
{
public:
A(int i){x=i;cout<<"调用A类的构造函数\n";}
~A(){cout<<"调用A类的析构函数\n";};
void get() {cout<<"A类中X的值为:"<<x<<endl;}
private:
int x;
};
class B
{
public:
B(int i,int j,int k):a(i),b(j),y(k){cout<<"调用B类的构造函数\n";}
A geta(){return a;}
A getb(){return b;}
~B(){cout<<"调用B类的析构函数\n";}
void gety(){cout<<"B类中y的值为:"<<y<<endl;}
private:
A a;
A b;
int y;
};
int main()
{
B b(1,2,3);
b.geta().get();
b.getb().get();
b.gety();
return 0;
}
友元类
如果某类B的成员函数会频繁的存取另一个类A的数据成员, 而A的数据成员的Private/Protectd限制造成B存取的麻烦, B只能通过A的Public的成员函数进行间接存取
把B做成A类的友元类,即A类向B类开放其Private/Protectd内容, 让B直接存取
友元类:一个类可以作另一个类的友元
友元类的所有成员函数都是另一个类的友元函数
友元类的声明:
friend class 类名;
友元类注意事项:
1、友元关系是单向的
2、友元关系不能被传递
3、友元关系不能被继承
4、有时候需要注意前向声明
#ifndef _TELE_CONTROLLER_H_
#define _TELE_CONTROLLER_H_
class Television;
class TeleController
{
public:
void VolumeUp(Television &tv);
void VolumeDown(Television &tv);
void ChanelUp(Television &tv);
void ChanelDown(Television &tv);
};
#endif // _TELE_CONTROLLER_H_
#include "TeleController.h"
#include "Television.h"
void TeleController::VolumeUp(Television &tv)
{
tv.volume_ += 1;
}
void TeleController::VolumeDown(Television &tv)
{
tv.volume_ -= 1;
}
void TeleController::ChanelUp(Television &tv)
{
tv.chanel_ += 1;
}
void TeleController::ChanelDown(Television &tv)
{
tv.volume_ -= 1;
}
#ifndef _TELEVISION_H_
#define _TELEVISION_H_
class TeleController;
class Television
{
friend class TeleController;
public:
Television(int volume, int chanel);
private:
int volume_;
int chanel_;
};
#endif // _TELEVISION_H_
#include "Television.h"
Television::Television(int volume, int chanel) : volume_(volume), chanel_(chanel)
{
}
#include "Television.h"
#include "TeleController.h"
#include <iostream>
using namespace std;
int main(void)
{
Television tv(1, 1);
TeleController tc;
tc.VolumeUp(tv);
return 0;
}
嵌套类,局部类:
局部类
局部类是指在函数中定义类。
(c++不能在函数中定义函数。c++在类中定义的函数也就是成员函数。)这个类以及由它创建的对象,都局限在该函数作用域中;必须在类内实现所有的成员函数,不能拿到类外。因为函数是不可以嵌套定义的;若类内含有静态数据成员,必须在该函数外初始化;类内不可含有静态函数成员;类中不可使用包裹它的函数所定义的除静态外的局部变量。
局部类
int a;
void fun()
{
static int s;
class A
{
public:
void init(int i) { s = i; }
};
A m;
m.init(10);
}
局部类的另一个用途是用来实现类型转化
class Interface
{
public:
virtual void Fun() = 0;
};
template <class T, class P>
Interface* MakeAdapter(const T& obj, const P& arg)
{
int x;
class Local : public Interface
{
public:
Local(const T& obj, const P& arg)
: obj_(obj), arg_(arg) {}
virtual void Fun()
{
x = 100;
obj_.Call(arg_);
}
private:
T obj_;
P arg_;
};
return new Local(obj, arg);
}
.内嵌类
是在类体内定义的又一个类。外面的类叫外围类。这个类以及由它创建的对象,都局限在外层类作用域中;
外界能否使用内层类,全在于访问权限;若能使用,定要以外围类::内层类格式来用;
是类组合演化的又一种类间关系,即组合或聚集成员不是产生于其它类,而是产生于内层类;内层类的成员函数,可以在类内实现,也可以在外层类之外实现;
内层类的成员函数对外围类的成员没有访问权,反之亦然
定义嵌套类的目的在于隐藏类名,减少全局的标识符,从而限制用户能否使用该类建立对象。这样可以提高类的抽象能力,并且强调了两个类(外围类和嵌套类)之间的主从关系。
class A
{
public:
class B
{
public:
…
private:
…
};
void f();
private:
int a;
}
其中,类B是一个嵌套类,类A是外围类,类B定义在类A的类体内。
2 对嵌套类的若干说明:
1、从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类的作用域内使用该类名时,需要加名字限定。
2、从访问权限的角度来看,嵌套类名与它的外围类的对象成员名具有相同的访问权限规则。不能访问嵌套类的对象中的私有成员函数,也不能对外围类的私有部分中的嵌套类建立对象。
3、嵌套类中的成员函数可以在它的类体外定义。
4、嵌套类中说明的成员不是外围类中对象的成员,反之亦然。嵌套类的成员函数对外围类的成员没有访问权,反之亦然。国此,在分析嵌套类与外围类的成员访问关系时,往往把嵌套类看作非嵌套类来处理。
异常
abort
于一个用C++写的程序,被加载至内存后运行,最终走向死亡。程序的死亡大致有三种:自然死亡,即无疾而终,通常就是main()中的一个return 0;自杀,当程序发现自己再活下去已经没有任何意义时,通常会选择自杀。当然,这种自杀也是一种请求式的自杀,即请求OS将自己毙掉。有两种方式:void exit(int status)和void abort(void)。他杀,同现实不同的是,程序家族中的他杀行径往往是由自己至亲完成的,通常这个至亲就是他的生身父亲(还是母亲?)。C++并没有提供他杀的凶器,这些凶器往往是由OS直接或者间接(通过一些进程库,如pthread)提供的。 自然死是最完美的结局,他杀是我们最不愿意看到的,自杀虽是迫不得已,但主动权毕竟还是由程序自己掌控的;abort被调用时,程序将直接退出,任何对象的析构函数都不会调用
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
using namespace std;
struct node {
double y;
node(){
cout<<"new"<<endl;
}
~node(){
cout<<"delete -- "<<y<<endl;
}
};
double hmean(node a, node b){
if(a.y == -b.y){
std::abort();
}
return 2.0*a.y*b.y/(a.y + b.y);
}
int main(){
node a, b, c;
while(scanf("%lf %lf", &a.y, &b.y)){
c.y = hmean(a, b);
printf("%lf\n",c.y);
}
return 0;
}
异常机制
对异常的处理有三个组成部分:
引发异常 捕获处理程序的异常 使用try
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
double hmean(double a, double b);
int main(){
double x, y, z;
printf("Enter two numbers :");
while(scanf("%lf %lf", &x, &y) != EOF){
try{
z = hmean(x, y);
}
catch(const char *s){
printf("%s",s);
continue;
}
printf("%f %f", x, y);
printf(" %f \n",z);
}
printf("BYE\n");
return 0;
}
double hmean(double a, double b){
if(a == -b)
throw "bad hmean() arguments : a = -b not allowed";
return 2.0 * a * b/(a + b);
}
堆栈解退
当抛出了异常,但还没在特定的作用域中被捕获时,函数调用堆栈便被“解退”,并试图在下一个外层try…catch代码中捕获这个异常。解退函数调用堆栈意味着抛出未捕获异常的那个函数将终止,这个函数中的所有局部变量都将销毁,控制会返回到原先调用这个函数的语句。
如果有一个try代码块包含了这条语句,则它就会试图捕获这个异常。如果没有代码块包含这条语句,则堆栈解退再次发生。如果没有任何catch处理器捕获这个异常,则会调用terminate函数,终止程序。
下面的demo演示了堆栈解退:
#include <iostream>
#include <stdexcept>
using namespace std;
void fun3() throw (runtime_error)
{
cout<<"In fun 3"<<endl;
throw runtime_error("runtime_error in fun3");
}
void fun2() throw (runtime_error)
{
cout<<"fun3 is called inside fun2"<<endl;
fun3();
}
void fun1() throw (runtime_error)
{
cout<<"fun2 is called inside fun1"<<endl;
fun2();
}
int _tmain(int argc, _TCHAR* argv[])
{
try
{
cout<<"fun1 is called inside main"<<endl;
fun1();
}
catch(runtime_error &error)
{
cout<<"Exception occurred: "<< error.what()<<endl;
cout<<"exception handled in main"<<endl;
}
system("pause");
return 0;
}
运行结果:
注意:
程序运行堆栈解退以回到能够捕捉异常的地方时,将释放对战中的自动存储型变变量,如果变量是类对象, 将为该对象调用析构函数
其他类异常特性
try-catch 跟 函数的区别:
函数调用返回时将控制权返回给调用其的函数, 而try-catch结构将控制权向上级返回。
exception类