c++ 学习 6

1. 拷贝构造

  • 拷贝构造函数:T(const T & )。(1)用对象初始化时,调用拷贝构造函数 (2)如果没有显示地定义拷贝构造函数,c++ 默认会给出拷贝构造函数,member-member wise 。成员变量直接赋值,成员指针,指向同一块内存,成员对象,递归调用成员对象的拷贝构造函数。
Currency p=bucks; //初始化,调用拷贝构造
p=bucks;          //赋值,调用运算符重载函数
T(T t) //ERROR,在调用时,会递归调用T(T t)
static int objectCount=0;
class howmany{
	public:
		howmany(){objectCount++;print("hommany()");}
        howmany(int i){objectCount++;print("hommany(int)");};
        howmany(const howmany & h){objectCount++;print("hommany(HM)");}
		void print(const string& msg=""){
		    if(msg.size()!=0) cout<<msg<<":";
		    cout<<"objectCount="<<objectCount<<endl;
		}
		~howmany(){
			objectCount--;
			print("~howmany()");
		}
		
}; 

howmany f(howmany x){
	
	cout<<"begin of f"<<endl;
	x.print("x argument inside f()");
	cout<<"end of f"<<endl;
	return x;
	
}
int main(){
	
	howmany h;//默认会调用无参构造,因此:hommany():objectCount=1
	h.print("after construction of h");
	howmany h2=f(h);  //(1)h初始化形参x  调用hommany(const hommay & h)
					  //(2)f返回hommany对象调用拷贝构造函数初始化h2      
	h.print("after call to f()");
}
  • 拷贝构造时,对于指针的指向同一块内存,delete时会出现错误。可以重新写拷贝构造函数。
    c++中推荐使用string而不是char *s,因为系统会默认给出拷贝构造函数。(c++标准类库的类以小写字母开头)
class Person
{

public:
    char *name;
    Person(const char *s)
    {
        name = new char[strlen(s) + 1];
        strcpy(name, s);
    };
    ~Person(){
        delete[] name;
    }
};

int main()
{
    Person p1("Joh");

    Person p2 = p1;   //member-member wise,成员指针name指向同一块内存。delete时会出错
    printf("p1.name=%p\n",p1.name);
    printf("p2.name=%p",p2.name);
    return 0;
}

  • 拷贝构造的调用时刻 (1)初始化; (2)函数以对象为参数(3)返回类型为对象
  • 返回类型为对象:
Person f(){
    return Person("John");
}
int main(){
    Person p=f(); //(1) Person @temp=f(); Person=@temp;
                  //or (2)  Person p=Person("John")
    return 0;
}
  • 推荐: (1)在写一个类时,写出拷贝构造,无参构造,虚函数构造(java 中没有拷贝构造这一说法,全是对象的引用,如果想要避免拷贝构造,可以将拷贝构造限定为私有)

静态变量

  • c中静态的作用: (1)永久访问 (在哪里)(2)访问受到限制(谁可见)
  • static变量就是全局变量,全局变量的构造函数的执行在main函数运行之前执行,全局变量的内存分配在编译(Link)时。
  • static 变量只在同一.c文件有效。
  • c++ 可以随便指定一块内存为一个对象,但java必须在new 以后才能拿到那块内存。
class X
{
private:
    /* data */
public:
    X(int i){};
};
void f(){                // 存储在全局数据区,在编译时(Link)时分配变量
    static X my_X(10);  //第一次进入函数时初始化,在my_X内部一定有hidde 变量来记录有没有初始化)
}

静态成员变量

  • 静态成员变量在被所有对象所共享并且保持一致。
  • 静态成员变量只能在定义时初始化,不能再initialist 中初始化;因为class {}中都是declaration,不是defination,因此对于静态成员变量必须采用这种方式定义。
class A
{
private:
    static int i;  //declation
public:
    A(){i=10;};
    void say(int ii){cout<<this->i<<endl;}
};
int A::i =10; //静态成员变量只能在定义式初始化,不能在initialist 中初始化
//static int A::i=10; //ERROR ,因为对象的成员变量可以在任何文件进行访问,static修饰后,表示只能在该文件访问
int main(){
    A a;
    a.say(2);

    return 0;
}
  • 静态成员函数,只能访问静态成员变量,不能访问非静态成员变量,根本在于静态成员函数没有隐藏变量this.
class A
{
private:
    static int i;  //declation
public:
    A(){i=10;};
    static void say(int ii){cout<<i<<endl;}
};
int A::i =10; 

int main(){
    A a;
    a.say(2);

    return 0;
}
  • 静态成员变量既有静态的属性,也有一般非静态成员的属性因此可以通过A::i 或a.i 访问。
  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值