[note] Effective C++ Note 5

Effective C++ Learning Note 5
(undergradute edition)

Implementations, and more on Inheritance

===========================================

postpone Definitions of vars

main purpose: avoid if:

  • in a function : return too early
  • throw an error

to sum up, to prevent a var unused.

another case: for an assigning loop

  • A: 1 ctor, 1 dtor, n assignments
  • B: n ctors, n dtors

normally, B plan is more likely to carry out the rule of encapsulation
so, use B unless:

  • you know exactly assignment is less expensive than a constructor-destructor pair.
  • you’re dealing with a performance-sensitive part of your code.

avoid returning “handles” to internals

encapsulation

class Rectangle
{
public:
    Point &upperleft() const { return pData->ulhc;}
    Point &lowerRight() const { return pData->lrhc;}
    ...
}

the const function is defined to remain the member unchanged. however, by returning a reference, we can astonishingly find we could change its private members!!!

dangling handles

when returning a reference or pointer, sometimes it may be just towards a expired “shell” then.

inlining

  • if we define a member function in one class, it’ll be implicitly conversed to inline function

public inheritance: is-a relationship

in the “All birds can fly, penguins are birds, penguins can’t fly, uh oh” problem, we have two main solutions:

  1. not to define void fly() in class bird
  2. when penguin obj calls the fly(), throw an exception

however, our program is advised to stop by the entrance it starts, that’s to say, alarms when compiling and suspends then.

if we don’t need to deal with problems like flying, now and in the future, we may not distiguish the flying-birds and those cannot, but in order to more vividly reflect the reality, we may need to distinguish then.

scope problems: avoid hide name

Our goal … however, is to know enough to avoid unpleasant surprises, and for that task, we already have plenty of information.

  • how names are found: from the local scope, to containing scope, then to namespace scope, finally global.
  • don’t hide existing name: don’t declare a var or function that is of the same name to an existing one (especially the non-virtual ones).
  • when hiding is unavoidable: attach using Base::mf1(); in the derived class
  • in public inheritance, hiding parts of functions or vars is somewhat incorrect (for the is-a relation).
  • in private inhe, when we need to just inherit partially, try forwarding function like this:
    class Base{
    public:
        virtual void mf1() = 0;
        virtual void mf1(int);
    };
    class Derived : private Base{
    public:
        virtual void mf1() { Base::mf1();}
    }
    Derived d;
    int x;
    d.mf1(); // right
    d.mf1(x); // wrong
    

distinguish the inheritance of interface and impl.

type interface implementation
non-virtual yes yes
impure virtual yes yes(polymorphic)
pure virtual yes no
原创文章 42 获赞 17 访问量 1516

猜你喜欢

转载自blog.csdn.net/weixin_45502929/article/details/105607239