重载4个辨识

函数名

函数形参表

类的名称

成员函数的const属性

 

函数指针

#include <iostream>

#include <vector>

#include <string>

using namespace std;

bool (*cmp)(int x,int y);

bool ls(int x,int y){

cout<<(x > y)<<endl;

}

int main(){

int a = 3,b = 4;

cmp = &ls;

cmp(a,b);

*cmp;

  

}

this指针一般用于解决重名问题和返回自身的值或者引用。例如:

struct A{

int a;

 

void test(int a){

this->a = a;

}

 

 普通对象可以调用const函数,也可以调用非const函数,但是const对象只能调用const函数。

#include <iostream>

#include <sstream>

#include <fstream>

#include <vector>

#include <string>

using namespace std;

class Person{

public :

Person(){

}

Person(int id,string name,int age):_id(id),_name(name),_age(age){

}

Person& set(int id,string name,int age){

 

_id = id;

_name = name;

_age = age;

return *this;

 

}

void print(ostream &os){

os<<_id<<endl;

os<<_name<<endl;

os<<_age<<endl;

}

void operator=(  Person &p1){

p1._age = _age;

p1._name = _name;

p1._id = _id;

 

}

private:

int _id;

string _name;

int _age;

};

class A{

public:

A(){

_count++;

}

    ~A(){

     --_count;

}

static int sum(){

return _count;

}

 

 

private:

static int _count ;

};

  int A::_count = 0;

int main(){

  

A a;

A b;

A c;

cout<<A::sum()<<endl;

    a.~A();

    b.~A();

    cout<<A::sum()<<endl;

 

 

}

const成员函数和普通函数可以构成重载

 

 

 

 

在有些时候我们必须使用初始化列表:

没有默认构造函数的类成员

const成员

引用类型的成员

有的类成员需要显式调用含参数的构造函数

为了防止隐式类型转换用explicit 加在构造函数前面

最后记住: 构造函数不能为const。

单例模式(把赋值和复制定义为私有)

如果你有一个带有虚函数功能的类,则它需要一个虚的析构函数,

1.如果一个类有虚函数功能,它经常作为一个基类使用

2.如果它是一个基类,它的派生类经常使用new来分配

3.如果一个派生类的对象使用new来分配,并且通过一个指向它的基类指针来控制,那么它经常通过一个指向它的基类指针来删除它。

 

const三种用法:

修饰形参:使得形参只读,不可被更改。

修饰返回值,禁止外界修改返回值。

修饰类的成员函数,禁止在函数体内修改本对象。

const是种常量语义(semantics),或者保护语义,而非const是一种修改语

如果要使用不在同一文件的变量,那个变量在那个文件中要被声明为static

 

 

 

C++ 之继承

这里我们总结下三种访问权限:

假设有有base类和derived类(public继承):

private成员作用域仅限于base内部

public成员作用域在所有位置

protected成员作用在basederived内部

我们这里采用的继承方式为public继承,如果一个类里面有publicprivateprotected成员,他们经过public继承,在派生类中的访问标号为:public、不可访问、protected

总结起来就是:

Private为个人日记,在派生类中无法被访问

Protected为家族秘籍,在派生类家族体系中可以访问

Public为完全公开的东西,在派生类中可以随意的访问

Private在派生类的内部不可见,但是通过基类本身的函数可以间接访问

这就说明了被派生类隐藏的函数可以通过指定基类的类名来调用。

子类可以正常调用从父类继承而来的函数

子类编写的函数,仍可以正常使用(包括构造函数)

通过子类Studnet s调用的默认是子类自己的版本,此时如果不显示的调用基类,编译会报错

#include <iostream>

#include <string>

#include <vector>

using namespace std;

class Person{

    public:

        Person(){}

        Person(int id,

               const string &name,

               int age)

            :id_(id),

             name_(name),

             age_(age)

        {}

 

        void set(int id,

                 const string &name,

                 int age)

        {

            id_ = id;

            name_ = name;

            age_ = age;

        }

 

        void print() const

        {

            cout << id_  << " " << name_ << " " << age_ << endl;

        }

 

    protected:

        int id_;

        string name_;

        int age_;

};

 

class Student : public Person

{

    private:

        string school_;

 

 

    public:

    void set(int id,

             const string &name,

             int age,

             const string &school)

    {

        id_ = id;

        name_ = name;

        age_ = age;

        school_ = school;

    }

 

 

    void print() const

    {

        cout << id_ << " " << name_

             << " " << age_ << " " 

             << school_ << endl;

    }

};

 

class Programmer : public Person

{

    private:

        string language_;

};

 

 

int main(int argc, const char *argv[])

{

    Student s;

//这里调用的是3个参数的版本,是否会结合到父类的set函数

S.set(12,zhangsan”,23);//编译出错

    s.Person::set(12, "zhangsan", 23);

    s.print();

 

   

    return 0;

}

C++之复制控制

复制和赋值,深拷贝和浅拷贝,深拷贝是拷贝指针指向的内存,即从新开辟一块空间。

 

禁止复制和赋值

#include <iostream>

#include <string>

#include <vector>

using namespace std;

 

 

/*

 * 凡是继承该类的对象,均不可复制和赋值

 *

 */

class NonCopyable

{

    public:

        NonCopyable() {};

        ~NonCopyable() {};

    private:

        NonCopyable(const NonCopyable &);

        void operator=(const NonCopyable &);

};

 

//这里注意采用私有继承

class Test : private NonCopyable

{

    

 

};

 

 

 

int main(int argc, const char *argv[])

{

    Test t;

    Test t2(t);

 

    Test t3;

    t3 = t;

    return 0;

}   //编译出错

子类对象赋值给父类对象,对象会切除

 Person p1;

    Student s1;

    s1.set(123, "zhangsan", 45, "longhua");

    s1.print();

 

    p1 = s1;//

p1.print();

输出:

123 zhangsan 45 longhua

123 zhangsan 45

基类的指针可以指向派生类,会丢失派生类的部分,例:

#include <iostream>

#include <string>

#include <vector>

using namespace std;

 

class Animal

{

    public:

        void display()

        {

            cout << "In Animal " << endl;

        }

};

 

class Cat : public Animal

{

    public:

        void display()

        {

            cout << "In Cat " << endl;

        }

};

 

class Dog : public Animal

{

    public:

        void display()

        {

            cout << "In Dog " << endl;

        }

};

 

 

int main(int argc, const char *argv[])

{

    Animal *pa;

 

    Cat c; 

    Dog d;

 

    pa = &c;

    pa->display();   // Animal

 

    pa = &d;

    pa->display(); // Animal

 

 

    return 0;

}

 

如果是虚函数则调用的是派生类的函数,这其实是一种动态绑定,俗称多态

派生类的指针可以直接转化为基类的指针;基类指针转化为派生类的指针是不妥当的

class Animal

{

    public:

        virtual void display()   //虚函数

        {

            cout << "In Animal " << endl;

        }

};

int main(int argc, const char *argv[])

{

    Animal *pa;

 

    Cat c; 

    Dog d;

 

    pa = &c;

    pa->display();   // Cat 

 

    pa = &d;

    pa->display(); // Dog

 

 

    return 0;

}

如果用基类的指针指向一个派生类的对象,析构时要把派生类的析构函数设为虚函数,否则派生类的对象没有delete

类的大小和的成员变量有关,如果类中只有方法则类的大小为1

纯虚函数,又叫抽象类,类似java中的接口

#include <iostream>

#include <string>

#include <vector>

using namespace std;

 

//这个类叫做抽象类

class Animal

{

    public:

        //纯虚函数

        virtual void run() = 0;

 

};

 

 

int main(int argc, const char *argv[])

{

    Animal a;

    return 0;

}

句柄类和智能指针

将指向派生类的指针放入一个类,该类的不同对象触发多态。句柄类需要重载->操作符。和句柄类类似智能指针重载了->*操作符,更像是对一个类进行了再次封装,为了更好的管理内存,一般用于那些含有指针作为属性的类

句柄例:

class Animal{

public :

virtual ~Animal(){};

virtual void display() const = 0;

virtual Animal *copy() const = 0;

};

class Cat : public Animal{

public:

void display()const{

cout<<"I am cat"<<endl;

}

Cat *copy() const{

return new Cat(*this);//  返回指针的地址 ,操作对象的指针 

}

};

 

class Dog:public Animal{

public:

void display()const {

cout<<"I am dog"<<endl;

}

Dog *copy() const {

return new Dog(*this);

}

};

 

class Bear:public Animal{

public:

void display()const {

cout<<"I am Bear"<<endl;

}

Bear *copy() const{

return new Bear(*this);

}

};

class Handle{

public:

Handle();

Handle(const Handle &a);

Handle(const Animal &a);

~Handle();

Handle &operator=(Handle &a);

Animal *operator->();

 

private:

Animal *str_;

};

#include "Handle.h"

 

Handle::Handle():str_(NULL){

}

Handle::Handle(const Handle &a):str_(a.str_->copy()){

}

Handle::Handle(const Animal &a):str_(a.copy()){

 

}

 

Animal *Handle::operator->(){

return str_;

 

}

 

Handle &Handle::operator=(Handle &a){

if(this != &a){  //地址和地址比较 

delete str_;

str_ = a.str_->copy();

}

return *this;

}

Handle::~Handle(){

delete str_;

}