zoukankan      html  css  js  c++  java
  • Effective C++第三遍

    试图调用private的copy或赋值函数是编译期错误,而调用没有具体定义的函数则是连接期错误。

    以对象管理资源;智能指针RAII(资源获取立即初始化)后都是对象,但有时候,比如(API的)函数参数要求的是原始资源的指针,这时候有两种方法:

    1、显式转换:智能指针提供了get成员函数可以直接获取原始资源:

    std::tr1::shared_ptr<Investment> pInv(createInvestment());

    int daysHeld(const Investment* pi);

    int days=daysHeld(pInv.get());

    2、隐式转换:智能指针重载了指针取值操作符(->和*);或者提供一个隐式转换函数。

    内置类型参数通常被设计为pass-by-value,STL的迭代器和函数对象通常也被设计为pass-by-value。而其他很多class通常被设计为pass-by-reference,因为pass-by-value参数采用复制,会有很多构造和析构的成本。

    public意味着不封装,而不封装几乎意味着不可改变,因为会涉及到(破坏)太多的用户代码。

     能够访问private变量的只有成员函数和friend函数。因此使用非成员函数,有更好的封装性。

    C++比较自然的做法是设计为非成员函数,然后位于目标class所在的同一个namespace内。

    只有当参数位于参数列内时,才允许隐式转换,所以r*2正确(调用r.operater*(2),这里2被隐式转换为有理数),但2*r错误(因为没有相应函数可调用);一个可行的方法是让*成为一个non-member函数:const Rational operator*(const Rational& lhs,const Rational& rhs)。这样2*r也正确,因为2和r都位于参数列内,都被隐式转换为有理数Rational。

    pimpl手法:以指针指向一个对象,内含真正数据。例如针对widget设计:

    首先定义一个类widgetImpl包含实际的数据,然后类widget包含一个私有成员是widgetImpl的指针widgetImpl*。

    全特化的写法:

    namespace std{
        template<>
        void swap<widget>(widget& a,widget& b){
            a.swap(b);
        }   
    }

    客户可以全特化std内的template,但不可以添加新的Template(或class或function或其他任何东西)到std里头。

    因此,为使swap在尽可能多的语境下被调用,需要同时在目标class所在命名空间内写一个non-member版本及一个std::swap特化版本。

    降低文件间的编译依存关系:

    如果引用或指针能完全任务,就不要使用对象(这样不需要知道对象的大小,而只需要指针);

    尽量以class声明式替换class定义式;

    为声明式和定义式提供不同的头文件。

    public继承:is-a ,适用于base classes身上的每一件事情一定也适用于派生类。现实中的is-a未必全适合这里的公有继承。

  • 相关阅读:
    动态代理练习2全站压缩流输出[response动态代理]
    动态代理练习3自定义数据库连接池[connection动态代理]
    类加载器
    Mysql中的数据类型对应于Java中什么数据类型
    使用网上流传的一个数据库连接池在Proxy.newProxyInstance处引起 java.lang.ClassCastException 问题的解决方法
    动态代理练习1全站字符编码过滤[request动态代理]
    用cocos2dx将helloworld实现出来了
    多线程的自动管理(线程池)
    互斥对象
    多线程的自动管理(定时器)
  • 原文地址:https://www.cnblogs.com/ph829/p/5280580.html
Copyright © 2011-2022 走看看