C++ study notes (7)-class

C++ study notes (7)-class

The basic idea of ​​classes is data abstraction and encapsulation. Encapsulation implements the separation of the interface and implementation of the class. Data abstraction is a programming technique that relies on separation of interface and implementation.

define abstract data types

Define the improved Sales_dataclass

struct Sales_data{
    std::string isbn() const { return bookNo; }
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
    // 数据成员
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
}
// Sales_data 的非成员接口函数
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);
  • A function defined inside a class is an implicit inlinefunction

  • All members must be declared inside the class, but the member function body definition can be inside or outside the class

  • thisIt is an implicit parameter of a member function, initialized by the address of the function object, a constant pointer, pointing to the object itself, and cannot be changed.

  • Constant member function ( const member function): A keyword is added after the parameter list of the member function constto modify the type of the implicit thispointer, making it a constant pointer to a constant object const Sales_data *const. Cannot bind to a const object because the default thistype is a const pointer to a non-const version of the class type Sales_data *const. thisConstant member functions cannot modify object contents.

    std::string isbn() const { return bookNo; }
  • Constant objects and references or pointers to constant objects can only call constant member functions

  • The compiler processes classes in two steps, first compiling class member declarations, then to member function bodies. Therefore, the member function body can freely use other members of the class.

Define class-related non-member functions

The class needs some auxiliary functions such as the above add, readetc. These functions belong to the interface component of the class, and do not actually belong to the class itself

  • If non-member functions are part of a class interface, the declarations of these functions should be in the same header file as the class

  • IO classes are types that cannot be copied, so they can only be passed by reference

    istream &read(istream &is, Sales_data &item)
    {
      double price = 0;
        is >> item.bookNo >> item.units_sold >> price;
        item.revenue = price * item.units_sold;
        return is;
    }

Constructor

The constructor is used to control the initialization process of its object.

  • The constructor has the same name as the class and has no return type

  • The constructor cannot be declared as const, when the object of the class is created , until the constconstructor completes the initialization process, the object really gets the 常量properties

  • Default Constructor : The class controls the default initialization process through a special constructor that does not require any arguments. When a class does not explicitly define a constructor, the compiler implicitly defines a default constructor, also known as合成的默认构造函数

  • If a class contains members of a built-in type or a composite type, it should be given an in-class initial value so that the class is eligible to use a synthetic default constructor, otherwise default-initialized and its value is undefined.

  • The new C++11 standard defines that use after the parameter list = defaultrequires the compiler to generate a constructor.

    struct Sales_data{
      Sales_data() = default;
    }
  • Constructor initializer list: responsible for assigning initial values ​​to one or more data members of the newly created object

    Sales_data(const std::string &s, unsigned n, double p): bookNo(s), units_sold(n), revenus(p*n) {}

Access Control and Encapsulation

  • C++ uses access specifiers to enhance encapsulation

    • Members defined after publicthe specifier are accessible throughout the program
    • A member defined privateafter a specifier can be accessed by class member functions, but not by code that uses the class
  • structand classthe default access permissions are not the same. classThe default for the keyword isprivate

  • Friend : A class can make other classes or functions friends of the class, so that other classes or functions can access its non-public members

    friend Sales_data add(const Sales_data&, const Sales_data&);
  • The friend declaration only specifies the authority of the model text, not the function declaration in the usual sense. It is better to declare the function again outside the friend declaration.

Other properties of the class

Class membership revisited

  • inlineIt can be used in the function declaration inside the class, and it can also be used in the function definition outside the class

  • Mutable data member (mutable) : never const, even if it is consta member of an object, i.e. a constmember function can change the value of a mutable member

    class A
    {
        public:
            void add() const
          {
              ++b;  // 成立,因为是可变成员 mutable
          }
      private:
            mutable int b;  // 即使在一个`const`对象内也能被修改
    }

*thismember function that returns

  • If a constmember function returns by reference *this, its return type will be a constant reference
  • constA member function can be overloaded by distinguishing whether it is or not , for reasons similar to whether a pointer in a function parameter isconst

class type

  • Forward declaration : The function declaration is separated from the definition. After the declaration, it is an incomplete type before the definition, that is, only the class type is known, but it is not clear which members are included
  • The use of incomplete types is very limited: you can define pointers or references to incomplete types, and you can also declare (but not define) functions that take incomplete types as parameters or return types.

Friends of Yuan revisited

Friendship between classes

class Screen{
    friend class Window_mgr;  // Window_mgr 的成员可以访问 Screen 类的私有部分
};
  • If the class specifies a friend class, the member functions of the friend class can access all members of this class, including non-public members
  • There is no transitivity in the friend relationship, that is, window_mgrthe friend class does not have access Screenprivileges
  • Each class is responsible for controlling its own friend class or friend function

Make member functions a friend

class Screen{
    friend void Window_mgr::clear(ScreenIndex);  // Window_mgr::clear必须在Screen类之前被声明
}

Friend Function Design Rules

  • First define Window_mgrthe class, in which clearfunctions are declared, but not defined. Must be declared before used clearmembersScreenScreen
  • Next define Screen, including clearfriend declarations for
  • Finally define a member clearat which point it can be usedScreen

Friend declarations and scope

  • The role of the friend declaration is to affect access rights, not a declaration in the ordinary sense

    struct X{
      friend void f() { /* 友元函数可以定义在类内部 */}
        X() { f(); }  // 错误:f 还没有被声明
        void g();
        void h();
    };
    void X::g() { return f(); }  // 错误:f 还没有被声明
    void f();  // 声明那个定义在 X 类中的函数
    void X::h() { return f(); }  // 正确:现在 f 的声明在作用域中了

class scope

  • A class is a scope, so defining a class member function externally needs to provide the class name and function name. Outside the class, the name of the member will be hidden

  • Member function definitions are not processed until the compiler has processed all declarations in the class

  • If the outer object is hidden, it can be accessed using the scope operator

    void Screen::dummy_fcn(pos height){
      cursor = width * ::height;   // 全局变量height
    }

Constructor revisited

Constructor initializer list

  • If the initializer member does not appear in the initializer list of the constructor, the member is default-initialized before the constructor body
  • The initial value of the constructor is initialization, and the assignment is performed in the body of the constructor
  • If the member is a const, reference, or some class type that does not provide a default constructor, it must be initialized via the constructor initializer list.
  • The difference between initialization and assignment is a matter of underlying efficiency
    • Initialization is the direct initialization of data members
    • Assignment is first initialization and then assignment
  • Member initialization order is consistent with the order in which they appear in the class definition, and try to avoid using some members to initialize other members
  • If a constructor provides default arguments for all parameters, it actually defines a default constructor as well

Delegate constructor

C++11 defines a delegating constructor : you can use other constructors of the class to which it belongs to perform its initialization process

class Sales_data{
    public:
        // 非委托构造函数使用对应的实参初始化成员
        Sales_data(std::string s, unsigned cnt, double price): bookNo(s), units_sold(cnt), revenue(cnt * price) {}
        // 委托构造函数将初始化过程委托给另一个构造函数,先执行被委托的上述构造函数,在执行本函数体
        Sales_data(): Sales_data("", 0, 0) {}
}
  • Execute the delegated constructor first, and then execute the delegator's function body

Implicit class type conversion

  • Conversion constructor : If the constructor accepts only one argument, it actually defines an implicit conversion mechanism to convert to this type of type, such a constructor is called a conversion constructor

    string null_book = '9-999=99999-9';
    // 构造临时Sales_data对象,对象的units_sold 和 revenue 为0, bookNo 等于 null_book
    item.combine(null_book);
  • The compiler will only perform one type conversion automatically

    // 错误:需要两步转换,先将字符串字面值转为string,再将临时的string对象转换成Sales_data对象
    item.combine("9-999-99999-9");
    item.combine(string("9-999-99999-9"));  // 正确:显示转换成 string,隐式转换成 Sales_data
  • explicitImplicit conversions can be prevented by declaring explicita constructor to be valid only for constructors with one argument, and constructors that require multiple arguments cannot be used to perform implicit conversions.

    class Salse_data{
      public:
            explicit Sales_data(const std::string &s): bookNo(s) {}
    }
  • The keyword can only be used when declaring a constructor inside a explicitclass, and should not be repeated when defining outside a class

  • explicitConstructors can only be used for direct initialization, not for copy initialization

Aggregate class

Aggregate class means that users can directly access its members, and has a special initialization syntax form, the conditions are as follows

  • all members publicare
  • no constructors defined
  • no in-class initializer
  • No base classes and no virtualfunctions

literal constant class

Requirements for Literal Constant Classes

  • Data members must be literal types
  • Class must have at least one constexprconstructor
  • If a data member has an in-class initial value, the initial value of the built-in type member must be a constant expression; or if the member is of a class type, the initial value must use the member's own constexprconstructor
  • A class must use the default definition of a destructor, the member responsible for destroying objects of the class
constexprConstructor

Constructors cannot be const, but constructors of literal constant classes can make constexprfunctions

constexpr Debug(bool h, bool i, bool o): hw(h), io(i), other(o) {}
  • constexprThe constructor must initialize all data members, the initial value uses the constexprconstructor or a constant expression

static member of class

A member associated with a class rather than an object is a static member, and a keyword can be added before the member declaration static. A static member can be publicOR private, and the type can be a constant, a reference, a pointer, or a class type, etc.

  • A static member function cannot be declared asconst

  • staticPointers cannot be used in the function body this, because static member functions are not bound to objects, and there are no thispointers

  • Static members can be accessed directly using scope operators, static members can be accessed using class objects, references or pointers

    double r;
    r = Account::rate();  // 使用作用域运算符访问静态成员
    Account ac1, *arc = &ac1;
    // 调用静态成员函数 rate 的等价形式
    r = ac1.rate();  // 通过 Account 的对象或引用
    r = ac2->rate();  // 通过指向 Account 对象的指针
  • Member functions can use static members directly without going through the scope operator

  • staticKeywords can only appear in declaration statements inside a class

  • Because static data members do not belong to any of the tired objects, static members cannot be initialized inside the class, each static member must be defined and initialized outside the class, and static data members can only be defined once

  • If the static member is of literal constant type constexpr, an in-class initial value of integer type can be provided for the static member const, and the initial value must be a constant expression

  • A static data member can have an incomplete type, in particular, the type of the class to which it belongs. Non-static members are restricted and can only be declared as pointers or references to the class to which they belong

  • Static members can be used as default arguments, but ordinary members cannot

Epilogue

Class is the most basic feature in the C++ language, and has two basic capabilities: data abstraction, which is the ability to define data members and function members; the second is encapsulation, which is the ability to protect class members from being freely accessed. privateEncapsulation is achieved by setting the implementation details of the class to . Classes can make other classes or functions friends so they can access non-public members of the class

Classes can define constructors, which are used to initialize objects. Constructors can be overloaded, all data members should be initialized using the constructor initializer list

A class can also define mutable or static members, a mutable member can never be const, and its value can be modified even within a constmember function; a static member can make a function or data, and a static member exists outside of all objects .

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325629108&siteId=291194637