Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

class ExInstanceRequired { int i;

public:

ExInstanceRequired() : i(0) {}

static

void

bad_mutate() { ++i *= 5; }

//

Error.

static

void

good_mutate(ExInstanceRequired& e) { ++e.i *= 5; } //

Good.

};

Due to not having a this pointer, their addresses can't be stored in pointers-to-member-functions, and are instead stored in normal pointers-to-functions.

struct ExPointer {

void nsfunc() {} static void sfunc() {}

};

typedef void (ExPointer::* mem_f_ptr)(); typedef void (*f_ptr)();

mem_f_ptr p_sf = &ExPointer::sfunc; // Error. f_ptr p_sf = &ExPointer::sfunc; // Good.

Due to not having a this pointer, they also cannot be const or volatile, nor can they have ref-qualifiers. They also cannot be virtual.

struct ExCVQualifiersAndVirtual {

 

static void

func()

{} // Good.

static void

cfunc() const

{} // Error.

static void

vfunc() volatile

{} // Error.

static void cvfunc() const volatile

{} // Error.

static void

rfunc() &

{} // Error.

static void rvfunc() &&

{} // Error.

virtual static void vsfunc()

{} // Error.

static virtual void svfunc()

{} // Error.

};

 

 

 

 

 

As they aren't tied to a given instance, static member variables are e ectively treated as special global variables; they're created when the program starts, and destroyed when it exits, regardless of whether any instances of the class actually exist. Only a single copy of each static member variable exists (unless the variable is declared thread_local (C++11 or later), in which case there's one copy per thread).

Static member variables have the same linkage as the class, whether the class has external or internal linkage. Local classes and unnamed classes aren't allowed to have static members.

Section 34.13: Multiple Inheritance

Aside from single inheritance:

class A {};

class B : public A {};

You can also have multiple inheritance:

class A {};

GoalKicker.com – C++ Notes for Professionals

191

class B {};

class C : public A, public B {};

C will now have inherit from A and B at the same time.

Note: this can lead to ambiguity if the same names are used in multiple inherited classs or structs. Be careful!

Ambiguity in Multiple Inheritance

Multiple inheritance may be helpful in certain cases but, sometimes odd sort of problem encounters while using multiple inheritance.

For example: Two base classes have functions with same name which is not overridden in derived class and if you write code to access that function using object of derived class, compiler shows error because, it cannot determine which function to call. Here is a code for this type of ambiguity in multiple inheritance.

class base1

{

public:

void funtion( )

{ //code for base1 function }

};

class base2

{

void function( )

{ // code for base2 function }

};

class derived : public base1, public base2

{

};

int main()

{

derived obj;

// Error because compiler can't figure out which function to call //either function( ) of base1 or base2 .

obj.function( )

}

But, this problem can be solved using scope resolution function to specify which function to class either base1 or base2:

int main()

{

obj.base1::function( ); // Function of class base1 is called. obj.base2::function( ); // Function of class base2 is called.

}

Section 34.14: Non-static member functions

A class can have non-static member functions, which operate on individual instances of the class.

class CL { public:

void member_function() {}

GoalKicker.com – C++ Notes for Professionals

192

};

These functions are called on an instance of the class, like so:

CL instance; instance.member_function();

They can be defined either inside or outside the class definition; if defined outside, they are specified as being in the class' scope.

struct ST {

void defined_inside() {} void defined_outside();

};

void ST::defined_outside() {}

They can be CV-qualified and/or ref-qualified, a ecting how they see the instance they're called upon; the function will see the instance as having the specified cv-qualifier(s), if any. Which version is called will be based on the instance's cv-qualifiers. If there is no version with the same cv-qualifiers as the instance, then a more-cv-qualified version will be called if available.

struct CVQualifiers {

 

void func()

 

{} // 1: Instance is non-cv-qualified.

void func() const

{} // 2: Instance is const.

void cv_only() const volatile {}

};

 

 

CVQualifiers

non_cv_instance;

const CVQualifiers

 

c_instance;

non_cv_instance.func(); // Calls #1.

c_instance.func();

 

// Calls #2.

non_cv_instance.cv_only(); // Calls const volatile version. c_instance.cv_only(); // Calls const volatile version.

Version ≥ C++11

Member function ref-qualifiers indicate whether or not the function is intended to be called on rvalue instances, and use the same syntax as function cv-qualifiers.

struct RefQualifiers {

void func() & {} // 1: Called on normal instances.

void func() && {} // 2: Called on rvalue (temporary) instances.

};

RefQualifiers rf;

rf.func(); // Calls #1. RefQualifiers{}.func(); // Calls #2.

CV-qualifiers and ref-qualifiers can also be combined if necessary.

struct BothCVAndRef {

void func() const& {} // Called on

void func() &&

{} // Called on

};

 

normal instances. Sees instance as const. temporary instances.

GoalKicker.com – C++ Notes for Professionals

193

They can also be virtual; this is fundamental to polymorphism, and allows a child class(es) to provide the same interface as the parent class, while supplying their own functionality.

struct Base {

virtual void func() {}

};

struct Derived {

virtual void func() {}

};

Base* bp = new Base; Base* dp = new Derived;

bp.func(); // Calls Base::func(). dp.func(); // Calls Derived::func().

For more information, see here.

GoalKicker.com – C++ Notes for Professionals

194