【参考】
【c++类基础】
类的定义
c语言结构体的升级版
类的成员可以是变量,可以是函数
定义一个类
class name
{
public:
void demo();
int age;
};
类的对象
类的实例化
直接定义
name Tom; // name is class, Tom is object
在堆里定义
name *Tom = new name;
删除对象 -> 只能和堆里定义对象类型,需要手动删除对象
delete Jack;
对象访问 -> 直接定义的用 . , 指针定义的用 -> , 访问方式与C一致
Tom.age = 20;
Jack->age = 21;
类的成员函数
在类里面声明与定义:
class name
{
public:
void test()
{
cout << "Are you the rescue for the monkey?"<<endl;
}
int age;
};
int main()
{
name Tom;
Tom.test();
}
类内声明类外定义:
class name
{
public:
void demo(); // use {} here leads to error. void demo(){} means this function does nothing here, you cannot define it outside the class later
};
void name::demo() // the return type must be placed first. without name:: it will be recognized as common funtion
{
cout << "Where is our master?"<<endl;
}
int main()
{
name Tom;
Tom.demo();
return 0;
}
访问函数与变量用法相同
类的访问修饰符号
public: 函数与变量公开,任何人都可以访问
private: 函数和变量只能在类内访问(只能在类的定义大括号里访问),不能通过对象访问(不能在其他函数里面通过实例化访问)
class name
{
private:
int age;
};
int main()
{
name Tom;
Tom.age = 20; // error!
return 0;
}
但是private可以通过公有的成员函数直接访问
class name
{
public:
void demo();
private:
int age;
};
void name::demo()
{
age = 20; // no need to set a variable again, just use it directly
cout << age<<endl;
}
int main()
{
name Tom;
Tom.demo();
return 0;
}
protected:函数和变量只能在类内访问(protected 的函数与变量也可以被公有的函数直接调用),但是可以被派生类访问
class name
{
public:
void demo();
protected:
int age;
};
void name::demo()
{
age = 20;
cout << age<<endl;
}
int main()
{
name Tom;
Tom.demo();
return 0;
}
类函数的重载特性:
可以在类内构造同名不同参函数,调用的时候会自动判断
class name
{
public:
void demo();
void demo(int a);
protected:
int age;
};
void name::demo()
{
cout << "hi"<<endl;
}
void name::demo(int a)
{
cout << a <<endl;
}
int main()
{
name Tom;
Tom.demo();
Tom.demo(20);
return 0;
}
类的构造函数与析构函数
析构函数:
假如定义了析构函数,当对象被删除或生命周期结束时会触发析构函数
构造函数:
假如定义了构造函数,当对象被创建时会触发构造函数
要点:
- 构造函数与析构函数必须与类名一模一样
- 析构函数要在前面加~,构造函数不用
- 构造与析构都必须是公有函数
- 构造与析构都没有返回值
class name
{
public:
name(){} // do nothing
~name(){}
};
class name
{
public:
name(); // define later
~name();
};
name::name() // no return
{
cout <<"It has been created."<<endl;
}
name::~name() // no return
{
cout <<"It has been released."<<endl;
}
int main()
{
name Tom;
return 0;
}
- 构造函数可以被重载(需要在堆内定义,否则默认调用无参构造函数),析构函数不能被重载
class name
{
public:
name();
name(int a);
~name();
};
name::name()
{
cout <<"It has been created."<<endl;
}
name::name(int a)
{
cout << a << endl;
}
name::~name()
{
cout <<"It has been released."<<endl;
}
int main()
{
name Tom;
name *Jack = new name; // use name();
delete Jack;
return 0;
}
class name
{
public:
name();
name(int a);
~name();
};
name::name()
{
cout <<"It has been created."<<endl;
}
name::name(int a)
{
cout << a << endl;
}
name::~name()
{
cout <<"It has been released."<<endl;
}
int main()
{
name Tom;
name *Jack = new name(20); // use name(int a); it must use (),if [] is used, [20] means it is a array, not a parameter
delete Jack;
return 0;
类的虚函数与纯虚函数
虚函数:有实际定义,允许派生类进行覆盖式替换
纯虚函数:没有实际定义的虚函数
virtual void test(); // virtual function
virtual void func(){} // Pure virtual function
虚函数定义:
使用virtual修饰,用于类的继承,虚函数的作用在于被子类修改后,调用基类指针访问对应的函数对应的是子类中修改后的值。
重点:在堆中实例化对象,指针前面使用基类指针,new的是子类的空间类型
class name
{
public:
int age = 10;
virtual void demo();
};
class nickname: public name
{
public:
int score;
void demo();
};
void name::demo()
{
cout << "demo in name" << endl;
}
void nickname::demo()
{
cout << "demo in nickname" << endl;
}
int main()
{
name Tom;
nickname *Jack = new nickname;
name *Peter = new nickname;
Tom.demo(); // demo in name
Jack -> demo(); // demo in nickname
Peter ->demo(); // demo in nickname
delete Jack;
delete Peter;
return 0;
}
好处:
可以隐藏细节,只暴露必要接口
可以管理不用的子类对象,统一用基类指针访问
统一使用基类指针方便作为参数传递给其他函数
注意:
c++规定,当一个成员函数被声明为虚函数后,其派生类的同名函数都自动成为虚函数。因此在派生类重新声明该虚函数时,可以加virtual,也可以不加,但习惯上一般在每层声明该函数时都加上virtual,使程序更加清晰。
虚函数必须在基类函数中定义,在子函数中可以不再定义,但是纯虚函数要么不定义,要么必须在子类中定义
class name
{
public:
int age = 10;
virtual void demo();
virtual void func(){}
};
class nickname: public name
{
public:
int score;
void func();
};
void name::demo()
{
cout << "demo in name" << endl;
}
void nickname::func()
{
cout << "func in nickname" << endl;
}
int main()
{
name Tom;
nickname *Jack = new nickname;
name *Peter = new nickname;
Tom.demo();
Jack -> demo();
Peter ->demo();
Peter ->func();
delete Jack;
delete Peter;
return 0;
}
类的继承
在新的类里面继承父类的public和protected部分, private不被继承
子类中访问父类成员也是通过 . 与 -> 访问。
class name
{
public:
int age;
};
class nickname: public name
{
public:
int score;
};
int main()
{
name Tom;
nickname *Jack = new nickname;
Tom.age = 10;
Jack->age = 20;
cout << Tom.age << endl; //10
cout << Jack->age << endl; //20
delete Jack;
return 0;
}
子类与父类中可以定义相同变量与函数,当都在类内完成初始化时,以子类的为准
class name
{
public:
int age = 10;
};
class nickname: public name
{
public:
int score;
int age = 16;
};
int main()
{
name Tom;
nickname *Jack = new nickname;
cout << Tom.age << endl; // 10
cout << Jack->age << endl; // 16
delete Jack;
return 0;
}
class name
{
public:
int age = 10;
void demo();
};
class nickname: public name
{
public:
int score;
void demo();
};
void name::demo()
{
cout << "demo in name" << endl;
}
void nickname::demo()
{
cout << "demo in nickname" << endl;
}
int main()
{
name Tom;
nickname *Jack = new nickname;
Tom.demo();
Jack->demo();
delete Jack;
return 0;
}
public继承方式
- 基类中所有 public 成员在派生类中为 public 属性;
- 基类中所有 protected 成员在派生类中为 protected 属性;
- 基类中所有 private 成员在派生类中不能使用。
protected继承方式
- 基类中的所有 public 成员在派生类中为 protected 属性;
- 基类中的所有 protected 成员在派生类中为 protected 属性;
- 基类中的所有 private 成员在派生类中不能使用。
private继承方式
- 基类中的所有 public 成员在派生类中均为 private 属性;
- 基类中的所有 protected 成员在派生类中均为 private 属性;
- 基类中的所有 private 成员在派生类中不能使用。
-> 和原本数据类型有关,也和继承类型有关,继承类型会将高于自己的类型拉到自己的水平,对低于自己水平的要么不予理会保持原样(public),要么直接禁止(三种类型对private)
class name
{
public:
int age = 10;
};
class nickname: protected name
{
public:
int score;
void demo();
};
void nickname::demo()
{
cout << age << endl;
}
int main()
{
name Tom;
nickname *Jack = new nickname;
cout << Tom.age << endl;
Jack->demo();
delete Jack;
return 0;
}