类成员指针
简介
有时我们可能需要类中成员的指针(static明显不算,这个不是类成员),这就是类成员指针,分为两种,类数据成员指针和类成员函数指针
eg://ClassMemberPointer.h
#ifndef __CLASS_MEMBER_POINTER__
#define __CLASS_MEMBER_POINTER__
#include <string>
#include <cstddef>
class Screen
{
public:
Screen():cursor(0),height(0),width(0){}
typedef std::string::size_type index;
char get() const;
char get(index ht,index wd) const
{
return 'a';
}
public:
std::string content;
index cursor;
index height;
index width;
};
#endif //__CLASS_MEMBER_POINTER__
//main.cpp
#include "ClassMemberPointer.h"
#include <iostream>
using namespace std;
typedef char (Screen::*pFunction)(Screen::index ht,Screen::index wd) const;
void action(Screen *screen,pFunction=&Screen::get);
int main()
{
//类数据成员指针
//格式:
//数据成员类型 类名::*指针名=&类名::数据成员;
std::string Screen::*pcontent=&Screen::content;
Screen::index Screen::*pindex;
pindex=&Screen::width;
pindex=&Screen::height;
//使用数据成员
//.* ->* 成员指针解引用/箭头
Screen s1;
Screen::index height=s1.*pindex;//解引用 pindex=&Screen::height;
Screen *s2=new Screen;
height=s2->*pindex;
cout<<height;//0
//类成员函数指针
//格式:
//返回值类型 (类名::*函数指针名)([形参表]) const=&类名::成员函数//如果是const的还要有const
//可以如下调用
//1.
//pFunction action=&Screen::get;
//2.通过typedef来使用函数action
Screen *screen=new Screen();
action(screen);
char ch;
cin>>ch;
return 0;
}
void action(Screen *screen,pFunction)
{
}
嵌套类
eg:
template <class Type>
class Queue
{
private:
struct QueueItem;
QueueItem *head;
QueueItem *tail;
};
template <class Type>//在外部定义嵌套类模板,在内部就不写了
struct Queue<Type>::QueueItem
{
QueueItem(const Type &t):item(t),next(0){}
Type item;
QueueItem *next;
}
局部类
1.明显只能在内部定义,你在外部定义个我看看。。
2.作用域太小了。。只在局部有作用
3.局部类只能访问外围作用域中定义的类型、static变量、枚举成员
eg:
int a,val;
void foo(int val)
{
int fooOuter();
static int si;//这算是外围作用域,可以访问,看第3条
enum Loc{a=1024,b};//同上
class Bar
{
public:
friend int fooOuter();//现在外外围作用域可以访问这个局部类的成员了。。
Loc locVal;//同上,这里使用了枚举类型名
int barVal;
void fooBar(Loc l=a)
{
barVal=val;//这不算是外围作用域了。。算外外围作用域//error
barVal=::val;//这使用了全局:://ok,全局
barVal=si;//ok,static
locVal=b;//ok,枚举
}
};
}
联合
这个虽然在c语言中就知道了。。但在c++中又有了点新东西
1.这是一个节省空间的类,同一时间只有一个数据成员有值,则其他都未定义。。存储内存需要与最大数据成员一样多
2.可以使用private、protected、public访问说明符
3.可以定义构造/析构函数,但不能有虚函数,即不能为基类
4.不能具有静态数据成员、引用成员、定义了构造/析构函数或operator=的类类型成员
eg:
union illegalMembers
{
Screen s;//has constructor,error
static int is;//error
int &rfi;//error
Screen *ps;//ok,一般指针类型
};
eg:
union TokenValue
{
char cVal;
int iVal;
double dVal;
};
//使用
TokenValue firstToken={'a'};
TokenValue lastToken;
TokenValue *pt=new TokenValue;
lastToken.cVal='z';
pt->iVal=2012;
嵌套联合
在类中经常会看到或者使用
eg:
class Token
{
public:
enum TokenKind
{
INT,
CHAR,
DBL;
};
TokenKind kind;
union
{
char cVal;
int iVal;
double dVal;
}val;
};
Token token;//class object
switch(token.kind)
{
case Token::CHAR:
token.val.cVal='A';
break;
case Token::INI:
token.val.iVal=99;
break;
case Token::DBL:
token.val.dVal=3.1415;
break;
}
匿名联合
eg:
class Token
{
public:
enum TokenKind
{
INT,
CHAR,
DBL;
};
TokenKind kind;
union //匿名union不能有private、protected成员,也不能定义成员函数
{
char cVal;
int iVal;
double dVal;
};
};
Token token;//class object
switch(token.kind)
{
case Token::CHAR:
token.cVal='A';
break;
case Token::INI:
token.iVal=99;
break;
case Token::DBL:
token.dVal=3.1415;
break;
}
固有的不可移植的特征
1.位域
算是c语言的东西了。。不过在二进制数据传递给另一程序或硬件设备时还是有用的
2.volatile
与const用法差不多
volatile类型的变量告诉编译器,本变量无需进行代码优化。在多线程的应用中,我们假如读入一个变量到寄存器,此时时间片到期,去处理其他线程了,在重新获得处理机时,volatile类型告诉处理机,重新从变量读取数据到寄存器,而不是用寄存器数据直接处理,这样能够防止脏数据
3.extern "C"
extern "FORTRAN"
extern "Ada"
有一个小要点,extern "C"因为c语言中没有重载函数这一说法,所以在一组重载的函数中只能为一个c函数指定链接指示
eg://如下就出错了,c语言中没有重载
extern "C" void print(const char*);
extern "C" void print(int);
extern "C" 函数的指针
extern "C" void (*pf)(int);