[C++ 面试基础知识总结] 类

来源:互联网 发布:adobe accc是什么软件 编辑:程序博客网 时间:2024/04/28 22:09

[C++ 面试基础知识总结] 类

参考书籍:《C++ Primer》

目录

  • C 面试基础知识总结 类
    • 目录
    • 类的基础
      • 成员函数
      • 构造函数
    • 访问控制和封装
    • 友元
    • 名字查找与类的作用域
    • 类的静态成员与普通成员

类的基础

成员函数

在成员函数中,可以直接访问数据成员,而在这个过程中实际上隐式地使用了一个名为this的隐式指针,该指针指向正是这个类对象。

#include <iostream>using namespace std;struct People{    string name = "Summer";    //return name等价于return this->name 或 return (*this).name    string getName() const{return name;};};int main(int argc, const char * argv[]) {    const People p{};    cout << p.getName() << endl;    return 0;}

重点注意:在语句string getName() const{return name;};中,const修饰的是this指针,在这里,this指针的默认类型为People *const,为指向非常量类型的常量指针。在函数后加上const声明,可以将this指针声明为const People *const类型。这里如果不加const声明的话,将会报错,因为类对象p是一个常量。

成员函数也可以在类外部定义,需要加上作用域运算符:

#include <iostream>using namespace std;struct People{    string name = "Summer";    string getName() const;};string People::getName() const{    return name;}int main(int argc, const char * argv[]) {    const People p{};    cout << p.getName() << endl;    return 0;}

构造函数

如果类没有声明任何构造函数,就会合成默认的构造函数。如果需要默认构造函数,需要定义。

#include <iostream>using namespace std;struct People{    string name = "Summer";    int age;    string getName() const{return name;};};int main(int argc, const char * argv[]) {    People p;    cout << p.name <<endl;  //存在类内初始值,输出"Summer"    cout << p.age << endl;  //不存在类内初始值,默认初始化,输出int型的默认初始值0    return 0;}

一旦定义构造函数,就不会自动生成默认构造函数

#include <iostream>using namespace std;struct People{    //默认构造函数    People() = default;    //参数数量不同的构造函数    People(const string &name): name(name){}    People(const string &name, int age): name(name),age(age){}    string name = "Summer";    int age = 26;    string getName() const{return name;};};int main(int argc, const char * argv[]) {    People p("7",24);    cout << p.name <<endl;    cout << p.age << endl;    return 0;}

使用默认构造函数时要注意去掉对象名后的空括号对。

//定义了一个没有形参返回类型为People的函数,而不是对象People p();//正确地使用默认构造函数初始化对象People p;

构造函数有一个隐式转换的规则,例如People类定义了一个接受string类型的构造函数,就可以在需要使用People的时候用string代替。

struct People{    //定义接受string类型的构造函数    People(const string &name): name(name),age(20){}     string name ;    int age ;    string getName() const{return name;};};void getAge(const People &p){    cout << p.age << endl;}int main(int argc, const char * argv[]) {    string s ="Summer";    // 用string替代People    getAge(s);    return 0;}

但是编译器只会自动地执行一步类型转换。

// 错误,隐式地使用了两种转换getAge("Summer");//正确,显示转换为string,再隐式转换为PeoplegetAge(string("Summer"));//正确,隐示转换为string,再显式转换为PeoplegetAge(People("Summer"));

如果不想通过构造函数,隐式地转换类,可以在构造函数前加上关键字explicit。然后就只能使用强制转换的方式了。

explicit People(const string &name): name(name),age(20){} 
// 错误,构造函数是explicit的getAge(s);// 正确,两种采用构造函数实行强制转换的方式getAge(People(s));getAge(static_cast<People>(s));

访问控制和封装

在C++中,class和struct唯一区别是,class中成员默认是private的,struct中成员默认是public。

using namespace std;class People{public:    string name = "Summer";    string getName() const{return name;};private:    int age = 26;   };
using namespace std;class People{    int age = 26; public:    string name = "Summer";    string getName() const{return name;};  };
using namespace std;class People{    string name = "Summer";    string getName() const{return name;};private:    int age = 26;   };

以上三个类完全一样。

友元

可以通过设置友元的方法来让其他函数访问类的私有成员。

using namespace std;class People{    //声明函数为People类的友元    friend int getAge(People &p);public:    string name = "Summer";    string getName() const{return name;};private:    int age = 26;};int getAge(People &p) {    //友元函数可以访问到People类的私有成员    return p.age;}

也可以设置其他类为类的友元。

using namespace std;class People{    //声明类Do为People类的友元    friend class Do;public:    string name = "Summer";    string getName() const{return name;};private:    int age = 26;};class Do{public:    void setAge();};void Do::setAge(){    People p;    //友元类的成员可以访问People类的私有成员    p.age = 20;}

也可以只让Do的成员函数setAge()成为People类的友元

using namespace std;//需要在声明友元函数前先声明友元函数所属的类class Do{public:    void setAge();};class People{    //声明函数为People类的友元    friend void Do::setAge();public:    string name = "Summer";    string getName() const{return name;};private:    int age = 26;};void Do::setAge(){    People p;    //友元函数可以访问到People类的私有成员    p.age = 20;}

名字查找与类的作用域

成员函数中使用的名字按照如下方式解析:
1.首先在成员函数内查找该名字的声明,只有在函数使用之前出现的声明才考虑。
2.如果成员函数内没有找到,则在类内继续查找,这时类的所有成员都可以被考虑。
3.如果类内也没有找到该名字的声明,在成员函数定义之前的作用域内查找。

typedef string Type;Type initVal();class Test{public:    typedef double Type;    //这里使用的Type为double    Type setVal(Type);    //要使用外层作用域的Type,需要用::显示指出,这里的前一个Type为string,后一个为double    ::Type setVal2(Type);    //这里使用的Type也为double    Type initVal();private:    int val;};//返回类型出现在函数名之前,返回类型在类的作用域外,需要用::指明所属的类Test::Type Test::setVal(Type t){    val = t + initVal();    return val;}//前一个Type是全局声明,后一个Type在类的作用域内,所以这里都不需要用::Type Test::setVal2(Type t){    return "";}

类的静态成员与普通成员

静态成员可以是不完全类型。

//声明一个不完全类型A,只知道A是一个类类型,不知道包含多少成员class A;class People{    static A p1; // 正确,静态成员可以是不完全类型    A *p2; // 正确,指针可以是不完全类型    A p3; // 错误,非静态成员必需是完全类型};

静态成员可以用作默认实参

class People{       static string name ;     string getName(string n = name ) const{return n;};};
1 0
原创粉丝点击