C++.Coding.Standards.1918.Rules.Guidelines [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

C++.Coding.Standards.1918.Rules.Guidelines [Electronic resources] - نسخه متنی

Herb Sutter, Andrei Alexandrescu

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید


Discussion


Although derived classes usually add more state (i.e., data members), they model

subsets , not supersets, of their base classes. In correct inheritance, a derived class models a special case of a more general base concept (see Item 37).Item 70) is correct only if the base class did not advertise that the operation always succeeds. For example, say

Employee offers a virtual member function

GetBuilding intended to return an encoding of the building where the

Employee works. What if we want to write a

RemoteContractor derived class that overrides

GetBuilding to sometimes throw an exception or return a null building encoding? That is valid only if

Employee 's documentation specifies that

GetBuilding might fail and

RemoteContractor reports the failure in an

Employee -documented way.

When overriding, never change default arguments. They are not part of the function's signature, and client code will unwittingly pass different arguments to the function, depending on what node of the hierarchy they have access to. Consider:

class Base {

// …
virtual void Foo( int x

= 0 );
};
class Derived : public Base {

// …
virtual void Foo( int x

= 1 );

// poor form, and surprise-inducing
};
Derived *pD = new Derived;
pD->Foo();

// invokes pD->Foo(1)
Base *pB = pD;
pB->Foo();

// invokes pB->Foo(0)

It can be surprising to callers that the same object's member function silently takes different arguments depending on the static type they happen to access it through.

Prefer to add the redundant

virtual when overriding a function. It makes the intent clearer to the reader.

Beware of inadvertently hiding overloads in the base class. For example:

class Base{

// …
virtual void Foo( int );
virtual void Foo( int, int );
void Foo( int, int, int );
};
class Derived : public Base {

// …
virtual void Foo( int );

// overrides Base::Foo(int), but hides the others
};
Derived d;
d.Foo( 1 );

// ok
d.Foo( 1, 2 );

// error (oops?)
d.Foo( 1, 2, 3 );

// error (oops?)

If the base class's overloads should be visible, write a

using declaration to redeclare them in the derived class:

class Derived : public Base {

// …
virtual void Foo( int );

// overrides Base::Foo(int)

using Base::Foo;

// bring the other Base::Foo overloads into scope
};


/ 521