zoukankan      html  css  js  c++  java
  • 类的其它属性

    类成员再探

    定义一个类型成员

    class Screen
    {
    public:
    	typedef std::string::size_type pos;
    	// using pos = std::string::size_type; //等价声明
    private:
    	pos cursor = 0;
    	pos height = 0, width = 0;
    	std::string contents;
    };
    

    用来定义类型的成员必须先定义后使用,类型成员通常出现在类开始的地方。

    成员作为内联函数

    在类中,常有一些规模比较小的函数适合被声明成内联函数。定义在类内部的成员函数 自动 inline

    可以在内部把 inline 作为声明的一部分显示的声明成员函数,同样也可以在类的外部用inline关键字修饰函数的定义。

    虽然无须在声明和定义的地方同时说明 inline,但这么做是合法的,不过,最好只在类外部定义的地方说明 inline,这样可以使类更容易理解。

    重载成员函数

    和非成员函数一样,成员函数也可以被重载。成员函数的匹配过程与非成员函数一样。

    可变数据成员

    如果想修改类的某个数据成员,即使是在一个 const 成员函数内,可以通过在变量的声明中加入 mutable 关键字。

    一个可变数据成员永远不会是const,即使它是const对象的成员。因此,一个const成员函数可以修改一个可变成员的值。

    class Screen
    {
    public:
    	void some_member() const;
    
    private:
    	mutable size_t access_ctr;
    };
    
    void Screen::some_member() const
    {
    	++access_ctr;  //尽管some_member是一个const成员函数,仍然能够修改可变数据成员
    }
    

    类数据成员的初始值

    当提供一个类内初始值时,必须以符合 (=) 或者花括号表示。

    返回 *this 的成员函数

    一个 const 成员函数如果以引用的形式返回 *this,那么它返回的类型将是常量引用。

    通过区分成员函数是不是const的,可以对其进行重载。

    class Screen
    {
    public:
    	Screen &display(std::ostream &os)
    			{do_display(os);return *this;}
    	const Screen &display(std::ostream &os) const
    			{do_display(os);return *this;}
    private:
    	void do_display(std::ostream &os) const {os << contents;}
    }
    

    display 调用函数 do_display 时,它的 this 指针将隐式地传递给 do_display 。而当 display的非常量版本调用 do_display 时,它的 this指针将隐式的转换成指向常量的指针。

    do_display 完成后,display 函数各自返回解引用所得的对象,在非常量版本中,this 指向一个非常量对象,因此 display 返回一个普通的引用,而 const 成员则返回一个常量引用。

    当我们在某个对象上调用 display 时,该对象是否是 const 决定了应该调用哪个版本的 display 函数:

    Screen screen1(5,3);
    const Screen screen2(5,3);
    screen1.display();	//调用非常量版本
    screen2.display();	//调用常量版本
    

    建议:对于公共代码使用私有的功能函数

    上面的 display函数为什么要费力单独定义呢:

    • 一个愿望是避免在多处使用相同的代码。
    • display 函数的功能随着发展变得更加复杂,此时把相应的操作写在一处便于统一修改。
    • 在开发过程中有可能给 display 函数添加一些打印信息,而这些信息在最终版本是要删除的,将其在一处添加和删除更容易。
    • 这个额外的函数定义在类内部,默认内联,所以不会增加开销。

    类类型

    每个类定义了唯一的类型,对于两个类来说,即使他们的成员完全一样,这两个类也是不同的类型。

    struct First
    {
    	int memi;
    	int getMem();
    }
    
    struct second
    {
    	int memi;
    	int getMem();
    }
    
    First obj1;
    Second obj2 = obj1; //错误,obj1和obj2的类型不同
    

    可以把类名作为类型名称直接使用,也可以把类名跟在关键字 class 或 struct 的后面:

    Sales_data item;
    class Sales_data item; //等价声明
    

    类的声明

    可以声明一个类而暂时不定义类,这种声明称为前向声明,它向程序中引入了这个类。

    class Screen;
    

    对于 Screen 来说,在它声明之后定义之前是一个不完全类型,也就是说我们已知 Screen 是一个类类型但是不清楚它包含了哪些成员。

    不完全类型的使用情景:

    • 可以定义指向这种类类型的指针和引用。
    • 也可以声明(不能定义)以不完全类型作为参数或返回类型的函数。

    对于一个类来说,在创建对象之前该类必须是被定义过的,而不能仅仅只是声明,否则编译器无法了解这样的对象需要占用多少存储空间。

    一个类的成员类型不能是其本身,但是可以包含指向其自身类型的引用或指针。

    class Link_screen{
    	screen window;
    	Link_screen *next;
    	Link_screen *prev;
    };
    

    友元再探

    类除了可以将非成员函数定义成友元函数之外,还可以将其他类定义成友元,也可以把其他类的函数定义成友元。

    友元函数能在定义在类的内部,这样的函数隐式内联。

    类之间的友元关系

    class Screen{
    	friend class Window_mgr;
    };
    

    如果一个类指定了友元类,则友元类的成员函数可以访问此类包含非公有成员在内的所有成员。

    但是需要注意的是,友元关系不具有传递性,也就是说如果 Window_mgr 有自己的友元,则这些友元并不具有访问 Screen 的特权。

    令成员函数作为友元

    class Screen{
    	friend void Window_mgr::clear(ScreenIndex);
    };
    
    • 必须指明友元函数所属的类。
    • Window_mgr::clear 函数必须在类 Screen 之前被声明。

    要想令某个成员函数作为友元,必须严格组织程序的结构以满足声明和定义彼此的依赖关系:

    • 首先定义 Window_mgr 类,其中声明 clear 函数,但是不定义它,因为 clear 函数将用到 Screen 的成员,在此之前必须先定义 Screen
    • 定义 Screen,包括对 clear 友元的声明。
    • 最后定义 clear,此时可以使用 Screen 的成员。

    函数重载与友元

    尽管重载函数的名字不同,但是他们仍然是不同的函数,因此如果想把一个类的一组重载函数声明为它的友元,需要对这组重载函数逐一声明。

    友元声明和作用域

    类和非成员函数的声明不是必须在它们的友元声明之前,当一个名字第一次出现在一个友元声明中时,隐式的假定该名字在当前作用域是可见的,然而友元本身不一定真的声明在当前作用域中。

    甚至就算在类的内部定义该函数,我们也必须在类外部提供相应的声明从而使该函数可见。

    struct X {
    	friend void f() {/*友元函数可以在类的内部定义*/}
    	X() { f(); }	//错误,f没有被声明
    };
    
    void f(); // 声明那个定义在X中的函数
    
    struct X {
    	friend void f() {/*友元函数可以在类的内部定义*/}
    	X() { f(); }	//正确
    };
    
  • 相关阅读:
    三元表达式
    迭代器
    python字符串内的自建函数 string.
    shell下的while和if
    正则表达
    nginx下同时做负载均衡和web服务
    nfs匹配nginx服务
    yum安装nginx的负载均衡详解
    samba实战讲解
    python基础之数据类型
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/12497791.html
Copyright © 2011-2022 走看看