char *cp = new char[100],ch[50];
int *p = new(cp) int ;
*p=58;
delete p;
cp = cp+sizeof(int);
delete cp;//错误,不能释放两次
int *p = new(ch) int ; //利用现有栈空间重新分配
delete *p ; //错误,不能释放栈空间
#include <iostream> using namespace std; class test{ friend ostream & operator << (const ostream &o,const test &t); }; ostream& operator << (ostream &o,const test &t){ cout <<"test"<<endl; return o ; } class Time{ public: int operator()() { //小括号重载 版本0 注意和下面用户自定义转换的区别 cout <<"bracket"<<endl; return h*3600 + m*60 + s; } operator test() { //用户自定义转换 1.用户定义的转换不能指定返回类型 2.“Time::operator test”: 必须返回一个值 cout <<"cast test"<<endl; static test t; //return t; //返回class test的一个引用 } void operator()(int h, int m, int s) { //小括号重载 版本3 this->h = h; this->m = m; this->s = s; } private: int h; int m; int s ; } ; int main(int argc,char**argv){ Time t; t(1,1,1) ; //小括号重载 ,并带有三个参数 cout<<t()<<endl;//小括号重载 版本0 cout<< test (t) ; return 0; }
const char* const foo(char const * const str) const
第一个const表示返回类型为const,也就是不能把此函数的返回值当作左值来使用。
第二个const表示指针的不可变性,但在这是可以省略,因为返类型已经是const。
第三个cosnt表示str的常量性,也就其内容是不能改变,可以写在其前面的char的前面。
第四个cosnt表示str的指针的常量性,也就是此指针不能指向别的地址。
第五个cosnt表示此函数的常量性(前提是类的成员函数),不能修改所在类的数据成员。
更详细的用法,参考:http://blog.csdn.net/Eric_Jo/article/details/4138548
下面还是用代码来说明问题
代码一:
const int m = 15; const int *const_p = &m; int *p = const_cast<int*> (const_p) ; *p = 18; cout << *p<<*const_p<<m; ;输出结果: 181815
代码二:
int m = 15; const int *const_p = &m; int *p = const_cast<int*> (const_p) ; *p = 18; cout << *p<<*const_p<<m; ;输出结果: 181818
代码三:
const int m = 15; const int &mconst = m; int &mnc =const_cast<int&>(mconst ); //或 int &mnc =const_cast<int&>(m); mnc = 80; cout << mnc <<mconst <<m;
输出结果:808015
这真是一件奇怪的事情,但是这是件好事:说明C++里是const,就是const,外界千变万变,我就不变。不然真的会乱套了,const也没有存在的意义了。
IBM的C++指南称呼“*modifier = 7;”为“未定义行为(Undefined Behavior)”。所谓未定义,是说这个语句在标准C++中没有明确的规定,由编译器来决定如何处理。
位运算的左移操作也可算一种未定义行为,因为我们不确定是逻辑左移,还是算数左移。
再比如下边的语句:v[i] = i++; 也是一种未定义行为,因为我们不知道是先做自增,还是先用来找数组中的位置。
对于未定义行为,我们所能做的所要做的就是避免出现这样的语句。对于const数据我们更要这样保证:绝对不对const数据进行重新赋值。
更详细的内容参考: http://www.cnblogs.com/ider/archive/2011/07/22/cpp_cast_operator_part2.html
C++中不可拷贝的对象一般为IO对象,不可拷贝的原因:io对象操作各种不同的输入输出设备的句柄,如果允许复制,会出现两个不同的对象操作同一个设备句柄,如果其中一个析构了,该设备被关闭,但另一个对象仍使用该句柄,会导致不可预测的运行期错误,是危险的。因此io对象不允许复制。
不可复制的实现:
在C++中,类的拷贝主要是通过拷贝构造函数和赋值函数,再者就是为拷贝专门实现的成员方法。由于拷贝构造函数和赋值函数在用户为提供的情况下是由C++编译器自动生成的,而且是public成员,因此默认的C++类都有拷贝功能。因此,可以显示的将构造函数和赋值函数设为私有成员,
在此留一下问题: 友员friend 是可以访问私友成员,如果让友员也不访问部分私友成员呢???
先看看下面一段代码:
#include <iostream> using namespace std; class A{ int m[15]; public: virtual void prinA(){cout <<"this is A"<<endl;} }; class B: public A{ //若换成虚继承,会有什么情况? public: virtual void prinB(){cout <<"this is B"<<endl;} }; void fun_1(A* pa){ B* pb = dynamic_cast<B*>(pa); if(pb==NULL){ pa->prinA(); }else{ pb->prinB(); } } void fun_2(A* pa){ B*pb=NULL; if(typeid(*pa)== typeid(B) ){ pb= static_cast<B*>(pa) ; pb->prinB(); }else{ pa->prinA(); } } int main(){ //cout <<sizeof(A)<<sizeof(B);//6464 A * pa =new B ; cout <<typeid(pa).name()<<endl; cout <<typeid(*pa).name()<<endl; fun_1(pa); fun_2(pa); A* paa = new A ; fun_1(paa); fun_2(paa); return 0; }
运行结果:
class A *
class B
this is B
this is B
this is A
this is A
Press any key to continue . . .
至于细仔的说明,这里就不弄出来了,给一个参考的链接吧!
更多细节参考:http://www.cnblogs.com/zhyg6516/archive/2011/03/07/1971898.html
在揭开typeid神秘面纱之前,我们先来了解一下RTTI(Run-Time Type Identification,运行时类型识别),它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid。
dynamic_cast允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型,与之相对应的还有一个非安全的转换操作符static_cast,因为这不是本文的讨论重点,所以这里不再详述,感兴趣的可以自行查阅资料。下面就开始今天我们的话题:typeid。
typeid是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为type_info的标准库类型的常量对象的引用(在头文件typeinfo中定义,稍后我们看一下vs和gcc库里面的源码),它的表达式有下图两种形式。
t1 == t2 | 如果两个对象t1和t2类型相同,则返回true;否则返回false |
t1 != t2 | 如果两个对象t1和t2类型不同,则返回true;否则返回false |
t.name() | 返回类型的C-style字符串,类型名字用系统相关的方法产生 |
t1.before(t2) | 返回指出t1是否出现在t2之前的bool值 |
#include <iostream> using namespace std; class A{ public: void action(){ cout << "Action in class A!" << endl; } }; class B{ A a; public: A* operator->(){ return &a; } void action(){ cout << "Action in class B!" << endl; } void printB(){ cout << "I am B" <<endl; } }; class C{ B b; public: B operator->(){ return b; } void action(){ cout << "Action in class C!" << endl; } }; int main(int argc, char *argv[]){ B b; //b->printB(); //error C2039: “printB”: 不是“A”的成员 b->action() ; //正确,调用 A::action() C* pc = new C; pc->action(); //正确,调用C::action(); C c; c->action(); //正确,调用C::operator-> ,再调用B::operator->,再调用A::operator->,最后调用A::action() getchar(); return 0; }