基于c的c++学习day2

面向对象基础

3.封装(重点)

把属性和行为作为一个整体表现生活中的事物

对属性和行为的加以权限限制

留有public接口方便访问

通常属性设为private加以权限,自己控制它的读写

#include <iostream>
using namespace std;
class Person{
private:
    string name; //可读可写
    string address; //只读
    string password="123456"; //只写

public:
    void set_name(string n){
        name=n;
    }
    void get_name(){
        cout<<name;
    }
    void get_address(){
        cout<<"华清远见"<<endl;
    }
    void set_password(string p){
        password=p;
    }
    void show(){
        cout<<name<<" "<<password<<endl;
    }
};
int main()
{
    Person p;
   //string s="hello";
    //p.name=s;错误 私有成员不能直接访问
    p.set_name("张三");
    p.show();
    p.get_address();
}

4.构造函数(重点)

构造函数是一个特殊的函数 :

名字和类名相同

没有返回值

如果不写系统会有默认的构造,如果给出就没有默认的构造函数。默认的构造函数函数体中没有任何内容,一般我都会重构一个构造函数来实现我想要的功能,默认的留着。

#include <iostream>
using namespace std;
class Person{
private:
    string name;
    string address;
    string password="123456";

public:
//    Person(){ //直接给出默认值 不灵活
//        name="张三";  
//        address="华清远见";
//        password="88888";
//    }
    Person(string n,string a,string p){
        name=n;
        address=a;
        password=p;
    }
    void set_name(string n){
        name=n;
    }
    void get_name(){
        cout<<name;
    }
    void get_address(){
        cout<<address<<endl;
    }
    void set_password(string p){
        password=p;
    }
    void show(){
        cout<<name<<" "<<password<<endl;
    }
};
int main()
{
    Person p("李四","济南","1234");
    p.get_address();
    p.get_name();
}

4.1构造函数默认值

#include <iostream>
using namespace std;
class Person{
private:
    string name;
    string address;
    string password="123456";

public:
//    Person(){
//        name="张三";
//        address="华清远见";
//        password="88888";
//    }
    Person(string n,string a="山东",string p="0000"){
        name=n;
        address=a;
        password=p;
    }
    void set_name(string n){
        name=n;
    }
    void get_name(){
        cout<<name<<endl;
    }
    void get_address(){
        cout<<address<<endl;
    }
    void set_password(string p){
        password=p;
    }

    void show(){
        cout<<name<<" "<<password<<" "<<address<<endl;
    }
};
int main()
{
    Person p("王五");
    p.get_address();
    p.get_name();
    p.show();

    Person p2("小明","青岛","88888888");
    p2.show();

    Person * p3=new Person("小红","上海","7777");
    p3->show();
    delete p3; //堆内存对象 需要delete
    p3=NULL;
}

4.2构造重载

#include <iostream>
using namespace std;
class Person{
private:
    string name;
    string address;
    string password="123456";

public:
    Person(){
        name="张三";
        address="华清远见";
        password="88888";
    }
    Person(string n,string a="山东",string p="0000"){
        name=n;
        address=a;
        password=p;
    }
    void set_name(string n){
        name=n;
    }
    void get_name(){
        cout<<name<<endl;
    }
    void get_address(){
        cout<<address<<endl;
    }
    void set_password(string p){
        password=p;
    }

    void show(){
        cout<<name<<" "<<password<<" "<<address<<endl;
    }
};
int main()
{
    Person p; //调用无参构造函数
    p.show();

}

4.3初始化列表

对属性进行初始化赋值

#include <iostream>
using namespace std;
class Person{
private:
    string name;
    string address;
    string password="123456";

public:
    Person(){
        name="张三";
        address="华清远见";
        password="88888";
    }
    Person(string n,string a,string p):                         name(n),address(a),password(p){}

    void set_name(string n){
        name=n;
    }
    void get_name(){
        cout<<name<<endl;
    }
    void get_address(){
        cout<<address<<endl;
    }
    void set_password(string p){
        password=p;
    }

    void show(){
        cout<<name<<" "<<password<<" "<<address<<endl;
    }
};
int main()
{
    Person p;
    p.show();

    Person p2("李四","济南","12345");
    p2.show();


}

5.析构函数 (掌握)

对象销毁时会自动调用,没有参数和返回值 也就不能重载

栈内存对象 编译器自动销毁 自动调用析构

堆内存对象 delete之后 自动调用析构函数

析构函数在对象销毁 做善后工作,回收new方式创建的资源,比如你的类属性中有指针类型那么当你深拷贝后,就要释放这个空间。

#include <iostream>
using namespace std;
class Cat{
private:
    string name;
public:
    Cat(string n):name(n){
        cout<<name<<"的构造函数调用"<<endl;
    }
    ~Cat(){
        cout<<name<<"的析构函数"<<endl;
    }
};
int main()
{
  Cat c("小花");
  Cat * c2=new Cat("小白"); //堆内存对象需要 手动delete
  delete c2;

}

6.作用域限定符(熟悉)::

std是c++中的标准命名空间,里面包含了很多内容。

using namespace std;

#include <iostream>
using namespace std;
int a=10;
namespace my_space {
    int a=30;
}
using namespace my_space; //使用创建的命名空间
int main()
{
  int a=20;
  cout<<a<<endl;
  cout<<"全局变量里的:"<<::a<<endl;
  cout<<"my_space里的"<<my_space::a<<endl;
  cout<<"hello"; //如果没有使用std命名空间 应是std::cout<<"hello";
  
}

作用域限定符应用

类的成员在类内做声明,类外定义时,类外定义需要加上作用域限定符

#include <iostream>
using namespace std;
class Student{
private:
    string name;
public:
    Student(string n){
        name=n;
    }
    void show(); //类内声明
};
void Student::show(){ //类外定义
    cout<<name;
}
int main()
{
    Student s("小明");
    s.show();
}

7.explicit(熟悉)

屏蔽隐式调用构造函数,防止误操作。

#include <iostream>
using namespace std;
class Student{
private:
    string name;
public:
    explicit Student(string n);
    void show(); //类内声明
};
void Student::show(){ //类外定义
    cout<<name;
}
Student::Student(string n):name(n){}
int main()
{
    Student s("小明");
    s.show();
    string str="小强";
//    Student s2=str; //隐式调用构造函数 加explicit后不允许
//    s2.show();
}

8.拷贝构造函数(掌握)

不手写编译器会默认添加一个拷贝构造函数

#include <iostream>
#include <string.h>
using namespace std;
class Phone{
private:
    string brand;
    string model;
public:
    Phone(string b,string m);
    void show();

};
Phone::Phone(string b,string m){
    brand=b;
    model=m;
}
void Phone::show(){
    cout<<brand<<" "<<model<<endl;
}
int main()
{
    Phone p("苹果","14");
    p.show();

    Phone p2(p);
    p2.show();

}

手写拷贝

对象之间相互独立 对象之间的属性也是独立的。只是把一个对象的值赋给了另一个对象

浅拷贝

#include <iostream>
#include <string.h>
using namespace std;
class Phone{
private:
    string brand;
    string model;
public:
    Phone(string b,string m);
    void show();
    Phone(const Phone & p){ //不写默认会有
        cout<<"拷贝构造函数"<<endl;
        brand=p.brand;
        model=p.model;
    }

};
Phone::Phone(string b,string m){
    brand=b;
    model=m;
}
void Phone::show(){
    cout<<brand<<" "<<model<<endl;
    cout<<&brand<<" "<<&model<<endl;
}

int main()
{
    Phone p("苹果","14");
    p.show();
    cout<<"------------"<<endl;
    Phone p2(p);
    p2.show();


}

值之间的传递。当属性有指针时出现问题

两个对象的成员变量保存同一个地址,指向同一片地址。

两个对象的

#include <iostream>
#include <string.h>
using namespace std;
class Dog{
private:
    char * name;
public:
    Dog(char * n){
      name=n;

    }
    void show(){
        cout<<name<<endl;
    }

    Dog(const Dog & d){
        name=d.name;
    }
};

int main()
{
    char a[10]="xiaobai";
    Dog d1(a);  //d1.name指向a
    Dog d2(d1); //d1.name也指向a

    d1.show(); //xiaobai
    d2.show(); //xiaobai
    strcpy(a,"doudou");
    d1.show(); //doudou
    d2.show();  //doudou
}

如果是属性中有指针类型,地址也会拷贝过去。破坏对象之间的独立性,就需要每个对象创建一个属于自己的空间

深拷贝

#include <iostream>
#include <string.h>
using namespace std;
class Dog{
private:
    char * name;
public:
    Dog(char * n){
      name=new char[20];
      strcpy(name,n);
    }
    void show(){
        cout<<name<<endl;
    }
    Dog(const Dog & d){
        name=new char[20];
        strcpy(name,d.name);
    }
};

int main()
{
    char a[10]="xiaobai";
    Dog d1(a);
    Dog d2(d1);
    d1.show(); //xiaobai
    d2.show(); // //xiaobai

    strcpy(a,"doudou");
    d1.show(); //xiaobai

    d2.show(); xiaobai

}
//堆
    Phone * p3 = new Phone("苹果","14");
    p3->show();
    Phone * p4 = new Phone(*p3);
    p4->show();

9.this指针(重点)

this指针指向当前对象的首地址

#include <iostream>
#include <string.h>
using namespace std;
class Test{
private:
    string str1;
    string str2;
public:
    Test(string str1,string str2){
        this->str1=str1;
        this->str2=str2;
    }
    void show(){
        cout<<this<<endl;
    }
    void method(){
        cout<<str1<<" "<<str2<<endl;
    }

};

int main()
{
    Test t2("1","2");
    cout<<&t2<<endl;
    t2.show();
    t.method();

}

9.1this指针应用1

this指针应用1:当参数和属性重名时 用this指针进行区分

#include <iostream>
#include <string.h>
using namespace std;
class Test{
private:
    string str1;
    string str2;
public:
    Test(string str1,string str2){
        this->str1=str1;
        this->str2=str2;
    }
    void show(){
        cout<<str1<<" "<<str2;
    }
    void show2(){
        this->show();
    }
    void method(){
        cout<<str1<<" "<<str2<<endl;
    }

};
int main()
{
//    Test t;
//    cout<<&t<<endl;
//    t.show();
    Test t2("1","2");
    t2.show2();
}

9.2this指针应用2 链式调用

函数返回值时 类的引用的时候,需要返回*this

#include <iostream>
#include <string.h>
using namespace std;
class Value{
private:
    int value=1;
public:
    Value & add(int i){
        value+=i;
        cout<<this<<endl; //地址都是一样的
        return *this; //*this是当前对象
    }
    void get_value(){
        cout<<value;
    }
};

int main()
{
    Value v;
    v.add(1).add(2).add(3).add(4);
    v.get_value();
}

10.static

static修饰局部变量 static只创建一次

#include <iostream>
#include <string.h>
using namespace std;
class Test{
public:
    void test(){
        int a=1;
        static int b=1;
        a++;
        b++;
        cout<<a<<" "<<b<<endl;
    }
};
int main()
{
    Test t;
    t.test(); //2 2
    t.test(); //2 3
    t.test(); //2 4
}

static修饰成员变量以下特点:

此类中所有的对象都共享此变量

非const 的静态成员变量 必须类里面声明 在类外初始化式

程序运行的时候创建,程序结束的时候销毁

#include <iostream>
#include <string.h>
using namespace std;
class Test{
public:
    static int a;
};
int Test::a=1;
int main()
{
    Test t1;
    cout<<t1.a<<" "<<&t1.a<<endl;
    t1.a++;
    Test t2;
    cout<<t2.a<<" "<<&t2.a<<endl;
}

静态函数

static修饰的函数

静态函数的特点;

静态成员函数不能访问类中的非静态变量。因为没有this指针,不具体作用于某个对象

静态成员函数不能访问类中的非静态函数

如果静态成员函数声明与定义分离的时候,只需要在声明出使用static关键字

#include <iostream>
#include <string.h>
using namespace std;
class Test{
public:
    static int a;
    int b=2;
    static void show(){
        //静态成员函数不能访问类中的非静态变量。
       // cout<<b<<endl;//相当于cout<<this->b<<endl;
    }
};
int Test::a=1;
int main()
{
    cout<<Test::a<<endl; //此时没有对象  也就没有this指针
    //cout<<Test::show(); 
}

静态函数访问非静态函数。

#include <iostream>
#include <string.h>
using namespace std;
class Test{
public:
    static int a;
    int b=2;
    void change(){
        b++;
    }
    static void show(){
        //change(); //b++  不可以,也会操作成员变量
    }
};
int Test::a=1;
int main()
{
    cout<<Test::a<<endl;
    //cout<<Test::show();
}

错误例子演示

#include <iostream>
#include <string.h>
using namespace std;
class Test{
private:
    int b;
public:
    static int a;
    void change(){
        b++;
    }
    Test(int bb){
        b=bb;

    }
    void show(){
        cout<<b<<endl;
    }
    static void show2(){
        cout<<b<<endl;
    }
};
int Test::a=1;
int main()
{
    Test t1(2);
    t1.show(); //t1.b=2

    Test t2(3); //t2.b =3
    t2.show();
    Test::show2();

}

10.const关键字

const表示常量的意思,意味着在运行的时候其修饰的内容不可以改,编译的时候可以更改

常成员函数

常成员函数就是在函数上加const关键字,其特点:

1.可以访问非const成员属性,但是不能更改其值

2.常成员函数也不能访问非const成员函数。

#include <iostream>
using namespace std;
class Test{
private:
    int a=1;
public:
    void get_a() const{
        //a++;错误
        cout<<a<<endl;
    }
    void set_a(){
        a++;
    }
    void method() const
    {
        cout<<a<<endl;
        //a++; 不能修改
        //set_a(); 错误

    }
};
int main()
{
    Test t;
    t.method();
}

当成员函数只读时 后面需加上const修饰

 

常量对象

const修饰的对象。特点:

1.常对象可以访问属性,但是不能修改其值

2.常对象不能调用任何const的成员函数

#include <iostream>
using namespace std;
class Test{
private:
    int a=1;
public:
    void get_a() const{
        cout<<a<<endl;
    }
    void set_a(){
        a++;
    }
    void method() const
    {
        cout<<a<<endl;
       
    }
};
int main()
{
    Test const t;
    t.get_a();
    //t.set_a(); 错误
    const Test t2;//const也可以放在Test前

}

常成员变量

const修饰的成员变量。就是常成员变量:

1.运行时常成员变量的值不可改

2.对它进行初始化 ,要么是定义的时候直接初始化。或者是构造函数初始化列表赋值

#include <iostream>
using namespace std;
class Test{
private:
    int a=1;
    const int b;
    const int c=4;//1.直接赋值
public:
//    Test(int a, int b){ //不能对b赋值
//        this->a=a;
//        this->b=b;
//    }
    //2.需要构造初始化列表来赋值
    Test(int a,int b):a(a),b(b=2){}
    void get_a() const{

        cout<<a<<endl;
        cout<<b<<endl;
        cout<<c<<endl;

    }
    void set_a(){
        a++;
    }

};
int main()
{
    Test t(2,3);
    t.get_a();

}

const修饰局部变量

给局部变量如参数加const修饰。函数参数值是不可以更改的

 

#include <iostream>
using namespace std;
class Test{
public:
    void func(const int b){
        //b++; 错误
        cout<<b<<endl;
        const int c=10;
        //c++; 错误
        cout<<c<<endl;
    }

};
int main()
{
    Test t1;
    t1.func(2);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值