??xml version="1.0" encoding="utf-8" standalone="yes"?>
1.const int r=100; //标准const变量声明加初始化Q因为默认内部连接所以必被初始化,其作用域为此文gQ编译器l过cd查后直接?00在编译时替换?nbsp;
2.extend const int r=100; //const改ؓ外部q接Q作用于扩大臛_局Q编译时会分配内存,q且可以不进行初始化Q仅仅作为声明,~译器认为在E序其他地方q行了定义?nbsp;
3.const int r[ ]={1,2,3,4};
struct S {int a,b;};
const S s[ ]={(1,2),(3.4)}; //以上两种都是帔R集合Q编译器会ؓ其分配内存,所以不能在~译期间使用其中的|例如Qint temp[r[2]];q样的编译器会报告不能找到常量表辑ּ
二、对于指?nbsp;
1.const int *r=&x; //声明rZ个指向常量的x的指针,r指向的对象不能被修改Q但他可以指向Q何地址的常量?nbsp;
2.int const *r=&x; //与用?完全{hQ没有Q何区别?nbsp;
3.int * const r=&x; //声明rZ个常量指针,他指向xQrq个指针的指向不能被修改Q但他指向的地址的内容可以修攏V?nbsp;
4.const int * const r=&x; //l合1?用法Qr是一个指向常量的帔R型指针?nbsp;
三、对于类型检?nbsp;
可以把一个非const对象赋给一个指向const的指针,因ؓ有时候我们不想从q个指针来修改其对象的|但是不可以把一个const对象赋值给一个非const指针Q因样可能会通过q个指针改变指向对象的|但也存在使这U操作通过的合法化写法Q用类型强制{换可以通过指针改变const对象Q?nbsp;
const int r=100;
int * ptr = const_cast<int *>(&r); //C++标准QC语言使用Qint * ptr =(int*)&r;
四、对于字W数l?nbsp;
如char * name = “china”; q样的语句,在编译时是能够通过的,但是”china”是常量字W数l,M想修改他的操作也能通过~译但会引vq行旉误,如果我们想修改字W数l的话就要用char name[ ] = “china”; q种形式?nbsp;
五、对于函?nbsp;
1.void Fuction1 ( const int r ); //此处为参C递const|意义是变量初g能被函数改变
2.const int Fuction1 (int); //此处q回const|意思指q回的原函数里的变量的初g能被修改Q但是函数按D回的q个变量被制成副本,能不能被修改没有了意义Q它可以被赋lQ何的const或非constcd变量Q完全不需要加上这个const关键字。但q只对于内部cd而言Q因为内部类型返回的肯定是一个|而不会返回一个变量,不会作ؓ左g用)Q对于用戯定义cdQ返回值是帔R是非帔R要的Q见下面条款3?nbsp;
3.Class CX; //内部有构造函敎ͼ声明如CX(int r =0)
CX Fuction1 () { return CX(); }
const CX Fuction2 () { return CX(); }
如有上面的自定义cCXQ和函数Fuction1()和Fuction2(),我们q行如下操作Ӟ
Fuction1() = CX(1); //没有问题Q可以作为左D?nbsp;
Fuction2() = CX(1); //~译错误Qconstq回值禁止作为左D用。因为左值把q回g为变量会修改其返回|const声明止q种修改?nbsp;
4.函数中指针的const传递和q回Q?nbsp;
int F1 (const char * pstr); //作ؓ传递的时候用const修饰可以保证不会通过q个指针来修改传递参数的初|q里在函数内部Q何修?pstr的企N会引L译错误?nbsp;
const char * F2 (); //意义是函数返回的指针指向的对象是一个const对象Q它必须赋给一个同h指向const对象的指针?nbsp;
const char * const F3(); //比上面多了一个constQ这个const的意义只是在他被用作左值时有效Q它表明了这个指针除了指向const对象外,它本w也不能被修改,所以就不能当作左值来处理?nbsp;
5.函数中引用的const传递:
void F1 ( const X& px); //q样的一个const引用传递和最普通的函数按g递的效果是一模一LQ他止对引用的对象的一切修改,唯一不同的是按g递会先徏立一个类对象的副本,然后传递过去,而它直接传递地址Q所以这U传递比按g递更有效?nbsp;
**另外只有引用的const传递可以传递一个时对象,因ؓ临时对象都是const属性,且是不可见的Q他短时间存在一个局部域中,所以不能用指针,只有引用的const传递能够捕捉到q个家伙?nbsp;
六、对于类
1.首先Q对于const的成员变量,只能在构造函数里使用初始化成员列表来初始化,试图在构造函C内进行初始化const成员变量会引L译错误。初始化成员列表形如Q?nbsp;
2.X:: X ( int ir ): r(ir) {} //假设r是类X的const成员变量
2.const成员函数。提到这个概念首先要谈到const对象Q正象内|类型能够定义const对象一Pconst int r=10;Q,用户自定义类型也可以定义const对象(const X px(10);)Q编译器要保证这个对象在其生命周期内不能够被改变。如果你定义了这L一个const对象Q那么对于这个对象的一切非const成员函数的调用,~译器ؓ了保证对象的constҎ,都会止q在~译期间报错。所以如果你惌你的成员函数能够在const对象上进行操作的话,p把这个函数声明ؓconst成员函数。假如f( )是类中的成员函数的话Q它的声明Ş如:
int f( ) const; //const攑֜函数的最后,~译器会对这个函数进行检查,在这个函C的Q何试图改变成员变量和调用非const成员函数的操作都被视为非?nbsp;
注意Q类的构造和析构函数都不能是const函数?nbsp;
3.建立了一个const成员函数Q但仍然想用q个函数改变对象内部的数据。这L一个要求也会经帔R刎ͼ其是在一个苛ȝ面试考官那里。首先我们要弄清楚考官的要求,因ؓ有两U方法可以实玎ͼ如果q位考官要求不改变原来类的Q何东西,只让你从当前q个const成员函数入手Q那么你只有使用前面提到的类型强制{换方法。实例如下:
//假如有一个叫做X的类Q它有一个int成员变量rQ我们需要通过一个const成员函数f( )来对q个rq行++r操作Q代码如?nbsp;
void X::f( ) const
{ (const_cast(this)) -> ++r; } //通过this指针q行cd强制转换实现
另外一U方法就是用关键字Qmutable。如果你的成员变量在定义时是q个样子的:
mutable int r ;
那么它就告诉~译器这个成员变量可以通过const成员函数改变。编译器׃会再理会对他的检查了?nbsp;
]]>
]]>
{
int i;
int a[10];
for(i=0; i<=10; i++)
{
a[i]=0;
printf("%d ",a[i]);
}
return 0;
}
]]>
http://www.hansencode.cn/category/tinyxml/
]]>
? 问题的提?br>C++ 不支持双分派Q只支持单分z。也是说参数的cd在~译阶段军_?虽然遇上同名函数的选取Ӟ没有体现多态,但进入函数后Q指针参数或引用参数仍然表现了其多?
下面的代码演CZ该问题:
using namespace std;
class D;
//B
class B
{
public:
void virtual output(B * b){cout << "B:B" << endl;}
void virtual output(D * d){cout << "B:D" << endl;}
};
class D : public B
{
public:
void output(B * b){cout << "D:B" << endl;}
void output(D * d){cout << "D:D" << endl;}
};
int main()
{
B * p1 = new D;
B * p2 = new D;
p1->output(p2);
return 0;
}D:B
? 解决Ҏ
Visitor设计模式
]]>template<class T> class Widget; // uses "class"
template<typename T> class Widget; // uses "typename"
然而,C++ q不L?class ?typename 视ؓ{同的东ѝ有时你必须使用 typename。ؓ了理解这一点,我们不得不讨Z会在一?templateQ模板)中涉及到的两U名字?br>
假设我们有一个函数的模板Q它能取得一?STL-compatible containerQSTL 兼容容器Q中持有的能赋值给 ints 的对象。进一步假设这个函数只是简单地打印它的W二个元素的倹{它是一个用p涂的方法实现的p涂的函敎ͼ而且像我下面写的,它甚至不能编译,但是请将q些事先攑֜一边——有一U方法能发现我的愚蠢Q?
template<typename C> // print 2nd element in
void print2nd(const C& container) // container;
{
// this is not valid C++!
if (container.size() >= 2)
{
C::const_iterator iter(container.begin()); // get iterator to 1st element
++iter; // move iter to 2nd element
int value = *iter; // copy that element to an int
std::cout << value; // print the int
}
}
print2nd 中的另一?local variableQ局部变量)value h int cd。int 是一个不依赖于Q?template parameterQ模板参敎ͼ的名字。这L名字?non-dependent namesQ非依赖名字Q闻名。(我想不通ؓ什么他们不U它?independent namesQ无依赖名字Q。如果,像我一P你发现术?"non-dependent" 是一个o人厌恶的东西Q你和我生了共鸣Q但?"non-dependent" 是q类名字的术语,所以,像我一P转{眼睛攑ּ你的自我d。)
nested dependent nameQ嵌套依赖名字)会导致解析困难。例如,假设我们更加愚蠢Cq种Ҏ开?print2ndQ?br>
template<typename C>
void print2nd(const C& container)
{
C::const_iterator * x;
//
}
直到 C 成ؓ已知之前Q没有Q何办法知?C::const_iterator 到底是不是一?typeQ类型)Q而当 templateQ模板)print2nd 被解析的时候,C q不是已知的。C++ 有一条规则解册个歧义:如果解析器在一?templateQ模板)中遇C?nested dependent nameQ嵌套依赖名字)Q它假定那个名字不是一?typeQ类型)Q除非你用其它方式告诉它。缺省情况下Qnested dependent nameQ嵌套依赖名字)不是 typesQ类型)。(对于q条规则有一个例外,我待会儿告诉你。)
Cq个Q再看看 print2nd 的开_
void print2nd(const C& container)
{
if (container.size() >= 2) {
C::const_iterator iter(container.begin()); // this name is assumed to
// not be a type
void print2nd(const C& container)
{
if (container.size() >= 2) {
typename C::const_iterator iter(container.begin());
}
}
typename 应该仅仅被用于标?nested dependent type nameQ嵌套依赖类型名Q;其它名字不应该用它。例如,q是一个取得一?containerQ容器)和这?containerQ容器)中的一?iteratorQP代器Q的 function templateQ函数模板)Q?br>
void f(const C& container, // typename not allowed
typename C::iterator iter); // typename required
"typename must precede nested dependent type names"Q?#8220;typename 必须前置于嵌套依赖类型名”Q规则的例外?typename 不必前置于在一?list of base classesQ基cd表)中的或者在一?member initialization listQ成员初始化列表Q中作ؓ一?base classes identifierQ基cL识符Q的 nested dependent type nameQ嵌套依赖类型名Q。例如:
class Derived: public Base<T>::Nested {
// base class list: typename not
public: // allowed
explicit Derived(int x)
: Base<T>::Nested(x) // base class identifier in mem
{
// init. list: typename not allowed
typename Base<T>::Nested temp; // use of nested dependent type
// name not in a base class list or
} // as a base class identifier in a
// mem. init. list: typename required
};
让我们来看最后一?typename 的例子,因ؓ它在你看到的真实代码中具有代表性。假设我们在写一个取得一?iteratorQP代器Q的 function templateQ函数模板)Q而且我们要做一?iteratorQP代器Q指向的 objectQ对象)的局部拷?tempQ我们可以这样做Q?br>
template<typename IterT>
void workWithIterator(IterT iter)
{
typename std::iterator_traits<IterT>::value_type temp(*iter);
}
如果你觉得读 std::iterator_traits<IterT>::value_type 令h讨厌Q就惌那个与它相同的东西来代表它。如果你像大多数E序员,对多ơ输入它感到恐惧Q那么你需要创Z?typedef。对于像 value_type q样?traits member namesQ特性成员名Q,一个通用的惯例是 typedef name ?traits member name 相同Q所以这L一?local typedef 通常定义成这P
template<typename IterT>
void workWithIterator(IterT iter)
{
typedef typename std::iterator_traits<IterT>::value_type value_type;
value_type temp(*iter);
}
作ؓl束语,我应该提及编译器与编译器之间对围l?typename 的规则的执行情况的不同。一些编译器接受必需 typename 时它却缺q代码Q一些编译器接受不许 typename 时它却存在的代码Q还有少数的Q通常是老旧的)会拒l?typename 出现在它必需出现的地斏V这意味着 typename ?nested dependent type namesQ嵌套依赖类型名Q的交互作用会导致一些轻微的可移植性问题?br>
Things to Remember
·在声?template parametersQ模板参敎ͼӞclass ?typename 是可互换的?br>
·?typename L?nested dependent type namesQ嵌套依赖类型名Q,?base class listsQ基cd表)中或在一?member initialization listQ成员初始化列表Q中作ؓ一?base class identifierQ基cL识符Q时除外?br>
]]>
例如:
你可以声明这样一个构造函?/p>
class Array
{
public:
explicit Array(int size);
//
};
Array arr;
//
arr = 40;
需要注意的?explicit同样也能L"以赋D法进行带有{型操作的初始?;
例如:
Array arr(40);//正确
Array arr = 40;//错误
X x;
Y y(x);//昑ּcd转换
X x;
Y y = x;//隐式cd转换
explicit关键字的应用主要是上面所说的构造函数定义中,参考该关键字的应用可以看看STL源代?其中大量使用了该关键?
]]>
对像的状态也会随之发生变?
如果一个类的成员函数被声明为constcd,表示该函C会改变对象的状?也就?br>该函C会修改类的非静态数据成?但是有些时候需要在该类函数中对cȝ数据成员
q行赋?q个时候就需要用到mutable关键字了
例如:
~译上面的代码会出现 error C2166: l-value specifies const object的错?br>说明在constcd的函C改变了类的非静态数据成?
q个时候需要用mutable来修C下要在const成员函数中改变的非静态数据成?br>m_nAccess,代码如下: