今天在看c++的视频学习的时候,有个问题很不解
代码如下:
#include <iostream>
using namespace std;
class A{
public:
A(int i){ cout<<"执行构造函数!\n";x=i;}
A(A&a){ cout<<"执行复制构造函数!\n";}
~A(){cout<<"析构函数!";}
int get(){ return x;}
private:
int x;
};
A func(){
cout<<"跳转!"<<endl;
A a(34);
cout<<"对象a的地址:"<<&a<<endl;
return a;
}
int main(){
A &r=func();
cout<<"对象a的副本地址:"<<&r<<endl;
cout<<r.get()<<endl;
return 0;
}
第21行代码编译报错:
|error: invalid initialization of non-const reference of type 'A&' from a temporary of type 'A'|
||=== Build finished: 1 errors, 0 warnings ===|
但是学习的视频代码没有错误,代码编译正常。
但在这行代码之前加个 const就可以通过编译。
即:const A &r=func(); //临时对象是const的
很不解的是视频上的是a的地址和a的副本地址不一样,即a的副本对象是调用构造函数创建的对象a的一个副本,也就是 说 两个对象不是一样的对象。
但是我在编译这段代码的时候,a和a的副本地址是一样的,析构函数也是输出一次。
注解:
函数返回一个对象值时,会产生临时对象,函数中的返回值会以值拷贝的形式拷贝到被调函数栈中的一个临时对象。
栈中对象都是系统自动分配的,堆中对象是delete删除的。
常量和引用只能初始化,不能赋值;
构造函数的初始化:
class rectangle{
public:
rectangle(int a,int b):length(a),total(b){}
private:
const int length;
int &total;
};
#include <iostream>
using namespace std;
class A{
public:
A(){}
//A(A&one){n=one.n;m=one.m;}
A(int a,int b){m=a;n=b;}
void print(){
cout<<n<<m;
}
private:
int m;
int n;
};
int main(){
A a(2,4);
a.print();
cout<<"\n";
A &c=a;
A b(c); //完成两个对象之间成员的拷贝。即 c拷贝到b
b.print();
return 0;
}
2013-06-02:
#include "mvk.h"
using namespace std;
class A{
public:
A(){ x=new int;*x=5;}
~A(){ delete x;x=NULL;}
void print() const{
cout<<*x<<endl;
}
void set(int i){*x=i;}
private:
int *x;
};
int main(){
A *a=new A();
cout<<"a:"<<endl;
a->print();
cout<<"b:"<<endl;
A b(*a);//这里两个对象的复制,可以写成:A b=*a; A*b=a;
b.print();
return 0;
}
由于a和b都指向同一块内存堆,当delete a后,a指向的堆删除了,b指针指向的内存区域也就不存在了,这时程序会报错。
2013-07-24
刚学c++的时候,对指针的表现方式很模糊,有时会产生矛盾的理解,比如说举个简单的例子来说:
#include <iostream>
using namespace std;
void reset(int *p){
*p=0;
}
int main (int argc ,const char *argv[]){
cout<<"begin:"<<endl;
int i=32;
int *p= &i;
cout<<"p的地址:"<<p<<endl;
reset(p);
p=0;
cout<<"p的地址:"<<p<<endl;
}
reset函数的参数int *p是个指针,调用的时候reset(p),有时候会这样理解why调用的reset不是reset(*p)呢(当然reset(*p)的调用方式是错误的),
而是reset(p)呢,其实可以这样理解,reset函数参数int *p可以写成int* p,int*是一种整型指针类型,p是变量名,即指针。
2013-07-25
typedef char* pStr;
char string[4] = "abc";
const char* p1 = string;// char* const p1=string;
const pStr p2 = string;
p1++; //这个是对的,如果换成注释的,那就不可以了。
p2++;//error
const pStr p2和const int x本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数据类型为char *的变量p2为只读,因此p2++错误。
函数指针的用法:
代码【1】
代码【1】
#include <iostream>
using namespace std;
int Max(int a, int b)
{
return a > b ? a : b;
}
typedef int (*pFun)(int, int);
pFun max_=&Max;//或者pFun max_=Max;
int main(int argc ,const char* argv[]){
int a = 3;
int b = 4;
cout<<"Test function pointer: "<<endl;
cout<<(*max_)(a,b)<<endl;//或者cout<<(max_)(a,b)<<endl;
}
代码【2】
#include <iostream>
using namespace std;
int Max(int a, int b)
{
return a > b ? a : b;
}
int Min(int a, int b)
{
return a < b ? a : b;
}
/*通用接口函数,实现对其他函数的封装*/
int Result(pFun fun, int a, int b)
{
return (*fun)(a, b);//(fun)(a,b)也可以
}
int main(int argc ,const char* argv[]){
int a = 3;
int b = 4;
cout<<"Test function pointer: "<<endl;
cout<<"The maximum number between a and b is "<<Result(Max, a, b)<<endl;
cout<<"The minimum number between a and b is "<<Result(Min, a, b)<<endl;
}
1) 函数指针的初始化。
函数如下:
2 {
3 return str1.compare(str2);
4 }
函数的初始化有两种方式:
第一种,也是最普遍的方式:
第二种,是使用typedef定义函数类型,这种写法有助于对代码的理解:
2 CompareFunctionType CompareFunction = CompareString;
2) 函数指针赋值。
函数名可以理解为该类型函数的指针。当然,取地址操作符作用于函数名上也能产生指向该类型函数的指针。也就是说下面两种赋值都是可行的:
2 CompareFunctionType CompareFunction = &CompareString;
3) 函数调用。
无论是用函数名调用,还是用函数指针调用,还是用显式的指针符号调用,其写法是一样的:
2 CompareFunction( " abc ", " cba ");
3 (*CompareFunction)( " abc " , " cba " );
参考:http://www.cnblogs.com/AnnieKim/archive/2011/11/20/2255813.html
代码【3】
#include <iostream>
using namespace std;
class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() { cout << "Base::g" << endl; }
virtual void h() { cout << "Base::h" << endl; }
};
int main (int argc ,const char *argv[]){
typedef void(*Fun)(void);
Base b;
Fun pFun = NULL;
cout<<&b<<endl;
cout<<(int*)*((int*)(&b))<<endl;
cout << "虚函数表地址:" << (int*)(&b) << endl;
cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;
// Invoke the first virtual function
pFun = (Fun)*((int*)*(int*)(&b));//不理解(Fun)*的含义
pFun();
}
函数指针参考:
http://blog.jobbole.com/44639/