C++ Primer - Chapter 7 (Classes) Flashcards

1
Q

What are the fundamental ideas behind classes?

A

Abstraction and encapsulation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What does “abstraction” mean?

A

A programming (and design) technique that relies on the separation of interface from implementation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What does “encapsulation” mean?

A

Encapsulation means hiding the code and data into a single unit (e.g. class or method) to protect the inner working of an object from the outside world.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
Fill in the blank:
A class that uses data abstraction and encapsulation defines a \_\_\_\_\_\_\_\_\_\_\_ type.
A

A class that uses data abstraction and encapsulation defines an abstract data type.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

True or false? Functions defined inside the class are implicitly inline.

A

True.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What type does “this” have? (When used inside a class object.)

A

A const pointer.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What implicit parameter is passed to a member function when the function is called from an object?

A

A const pointer to “this”.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

The “this” pointer is implicitly passed to a member function, so it cannot be made a pointer to const. How do we ensure that a member function does not alter the object?

A

By adding a “const” after the parameter list of the function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

True or false? A const object, and references or pointers to const objects, may call nonconst member functions.

A

False. A const object, and references or pointers to const objects, may only call const member functions.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What is the term given to function of a class which contains a const after its parameter list?

A

A const member function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Why can the body of a member function use member data that is declared after the member function is?

A

Because the compiler processes member declarations before processing the body of a member function (if there is one).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

How does a compiler process a class?

A

First, the compiler processes member declarations of the class, after which the member function bodies, if any, are processed.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What operator must be used to define a member function outside a class?

A

The scope operator, “::”.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

True or false? IO objects used to read or write can be passed as parameters of a function as references to const.

A

False, reading or writing to a stream changes that stream so it can only be passed by reference (it cannot be copied either).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q
What does the condition in the if-statement below do?
istream &read(istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
if (read(read(cin, data1), data2))
{
/*...*/
}
A

It checks that both data1 and data2 have been read in correctly.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What member functions are responsible for initialising the member data of a class object?

A

Constructors.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

What return type does a constructor have?

A

Trick question; a constructor does not have a return type.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q
Where is the error in the following code?
class SillyHuman
{
public:
SillyHuman() const {}
private:
int variableA=10;
int variableB=variableA;
};
A
class SillyHuman
{
public:
SillyHuman() const {}
// This is an error; a constructor can never be const.
private:
int variableA=10;
int variableB=variableA;
};
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q
What is the problem with the following code?
class SillyHuman
{
public:
SillyHuman() {variableA=10;}
private:
const int variableA;
};
A
class SillyHuman
{
public:
SillyHuman() {variableA=10;}
// Const member data can only be initialised using the constructor initialiser list.
private:
const int variableA;
};
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

True or false? It is an error to create a class without a constructor.

A

False. The compiler can generate a synthesised constructor (but it is a bad idea to rely on a synthesised constructor).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

If the definition of a class object contains no initialiser, how are the members of that object initialised?

A

Through the default constructor.

The default constructor is one that takes no argument.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q
Suppose a class named "Sales_data" is defined. What is the issue with the following default initialisation of the object "total"?
Sales_data total();
A
Sales_data total();
// The compiler will mistake "total" as the name of a function that takes no arguments and returns an object of type Sales_data.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

What is the name given to the compiler-generated constructor? (If no constructor is provided.)

A

The synthesised constructor.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

How does the synthesised constructor initialise each member data of the class?

A

It first checks if there is an in-class initialisation (C++11) of the member data; if there is not, it will default initialise the variable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

How many arguments must a default constructor take?

A

None.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

Why is it a bad idea to rely on the compiler to generate a synthesised constructor?

A

Because member data may become uninitialised. This can occur if the variable does not have a default constructor or it is a built-in or compound type

(Note: remember that objects of built-in type or compound type defined inside a block had undefined value when they are initialised.)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q
Is there an error in the following code? If so, where?
class SillyHuman
{
int variableA;
};
int main()
{
    SillyHuman human;
}
A
// The code below contains no errors. The compiler can create a default initialiser to initialise the value of variableA.
class SillyHuman
{
int variableA;
};
int main()
{
SillyHuman human;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q
Is there an error in the following code? If so, where?
class SillyHuman
{
public:
SillyHuman(int a) : variableA(a) {}
private:
int variableA;
};
int main()
{
    SillyHuman human;
}
A
class SillyHuman
{
public:
SillyHuman(int a) : variableA(a) {}
private:
int variableA;
};
int main()
{
SillyHuman human;
// This is an error; the class SillyHuman already contains a constructor, and the compiler assumes that if the user needs to control the initialisation of an object in one case, it will need to in all cases.
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

How can a constructor that takes no arguments be chosen to be the default constructor? (C++11)

A

By adding “=default” after the parameter list (C++11).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
Q

Where does the constructor initialiser list go?

A

After the constructor parameter list; it is preceded by a colon.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
31
Q

If member data is not initialised in the constructor initialiser list, how will it be initialised?

A
When a member is omitted from the constructor initialiser list, it is implicitly initialised using the same process as is used by the synthesised default
constructor (i.e. it will use the in-class initialiser (C++11), if there is one, and if not, it will be default initialised).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

How can encapsulation be enforced in a class?

A

By the inclusion of access specifiers (e.g. “public” and “private”).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
33
Q

If a constructor initialiser list is empty, what value will member data have inside the constructor body?

A

Member data will be default initialised before the constructor body is executed.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
34
Q

What is the sole difference between a struct and class?

A

By default, all members of a struct are “public” and all members of a class are “private”.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

How can a class access the members of another class?

A

By being made a friend of that class (i.e. the one being accessed).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
36
Q

True or false? A friend declaration of a member function is an “official” declaration of that function.

A

False. A friend declaration only specifies access; it is not a general declaration of the function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
37
Q

Do compilers enforce the rule that friend functions must be declared outside the class before they can be used?

A

No. Well, most compilers do not.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
38
Q
Is there a problem with the following code? If so, why?
class Screen {
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
public:
typedef std::string::size_type pos;
};
A
class Screen {
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
public:
typedef std::string::size_type pos;
// Here is the error; unlike other member data, members that define types must be declared before they are used. 
};
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
39
Q

True or false? It is an error to provide an inline specifier before both the declaration and definition of a function (if they are separate).

A

False. It is legal to specify that a function is inline in both its declaration and definition.

Note: as member functions defined inside the class body are implicitly inline, it can make it easier to read if the inline specifier is only used before the function definition.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
40
Q

How can we ensure that a member of a class can be modified, even inside a const member function?

A

By declaring that member to be mutable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
41
Q

True or false? A mutable member data can sometimes be const.

A

No, a mutable member data is never const, even if it is a member of a const object.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
42
Q

(C++11:) What is the syntax for in-class initialisation?

A

The member data must either be followed by an “=” and the defined value or inside a braced list.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
43
Q

(C++11:) True or false? Member data of class type cannot be initialised using in-class initialisation.

A

False.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
44
Q

What is the return type of a member function that returns “*this”?

A

The return type should be a reference to const.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
45
Q

What is the term given for the declaration of a class before it is defined?

A

A “forward declaration”.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
46
Q

What is the type of a class after it has been declared and before it has been defined?

A

An “incomplete type”.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
47
Q

In what ways can an incomplete type be used?

A

In a limited number of ways: by defining pointers or references to such types or declaring functions (not defining) that use an incomplete type in their parameter list or return type.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
48
Q

True or false? It is possible to use code that creates objects of an incomplete type.

A

False.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
49
Q

True or false? A class can contain members of the same type as the class itself.

A

False. The class is still an incomplete type when the declaration of its members are being processed.

50
Q

True or false? A class must be defined before pointers or references can be used to access a member of the type.

A

True. Declarations of pointers can be made when a class is an incomplete type but it cannot be used to access the data inside the class until its definition is complete.

51
Q

Does a class or a nonmember function need to be declared before it is used in a friend declaration?

A

No, it is implicitly assumed to be part of the surrounding scope. However, it needs to be declared outside the class before it becomes visible in that scope, even if it is defined inside the friend declaration.

52
Q

Can a class or a nonmember function be used if it is only declared or defined through a friend declaration?

A

No. It is not visible until it has been declared outside of the class.

53
Q

Why must a class be complete for objects of that type to be defined?

A

Because the compiler must know how much storage is required for each data member.

54
Q

When is a class considered to be declared?

A

As soon as its name is seen.

55
Q
Where is the error in the following code?
struct X {
friend void f() { ... }
X() { f(); } 
void g();
void h();
};
void X::g() { return f(); } 
void f();
void X::h() { return f(); }
A
struct X {
friend void f() { ... }
X() { f(); } 
// This is an error; f has not been declared (outside of the class) yet.
void g();
void h();
};
void X::g() { return f(); } 
// This is an error; f has not been declared (outside of the class) yet
void f(); 
void X::h() { return f(); }
56
Q

Why must we provide the class name as well as the function name when we define a member function outside its class?

A

The class is a scope. Outside of the class, the names of the members are hidden. We must therefore provide the class name as well as the function name to resolve the scope (in conjunction with the scope operator, “::”).

57
Q

Why do need to provide the class name as well as the function name when we define a member function outside its class, but not inside the function itself when we refer member data?

A

Once the class name is seen, the remainder of the definition, including the parameter list and function body is in the scope of the class. This does not include the return type, however.

58
Q
Where is the error in the following code?
class Screen {
// Window_mgr members can access the private parts of class Screen
friend class Window_mgr;
// . . . rest of the Screen class
};
class Window_mgr {
public:
using ScreenIndex = std::vector::size_type;
ScreenIndex addScreen(const Screen&);
};
ScreenIndex Window_mgr::addScreen(const Screen &s)
{
screens.push_back(s);
return screens.size() - 1;
}
A
class Screen {
// Window_mgr members can access the private parts of class Screen
friend class Window_mgr;
// . . . rest of the Screen class
};
class Window_mgr {
public:
using ScreenIndex = std::vector::size_type;
ScreenIndex addScreen(const Screen&);
};
ScreenIndex
Window_mgr::addScreen(const Screen &s)
// This is an error; the return type is seen before we’re in the scope of Window_mgr so must be written as Window_mgr::ScreenIndex.
{
screens.push_back(s);
return screens.size() - 1;
}
59
Q

Can a name defined in an outer scope normally be redefined inside a class?

A

Normally, yes, even if that name has already been used inside the inner scope.

60
Q

Can a name that is a type defined in an outer scope be redefined inside a class?

A

No; this is a special case where it is not possible to redefine a name inside a class.

61
Q

What is a special case where it is not possible to redefine a name inside a class?

A

When that name is a type.

62
Q

Where should definitions of type names typically be placed in classes? Why?

A

At the top of the class, to ensure that names defined in an outer scope are redefined before they are used. This is also because type names are not processed before they are used in a member function body, unlike most member data.

63
Q
Where is the error in the following code?
typedef double Money;
class Account {
public:
Money balance() { return bal; } 
private:
typedef double Money;
};
A
typedef double Money;
class Account {
public:
Money balance() { return bal; } 
// This uses Money from the outer scope.
private:
typedef double Money; 
// This is an error; we cannot redefine Money
Money after it has been used inside the class.
};
64
Q

How is a name used in the body of a member function typically resolved? I.e. in which order does the compiler search for a matching name?

A

• First, look for a declaration of the name inside the member function. As usual, only declarations in the function body that precede the use of the name
are considered.

  • If the declaration is not found inside the member function, look for a declaration inside the class. All the members of the class are considered.
  • If a declaration for the name is not found in the class, look for a declaration that is in scope before the member function definition.
65
Q
Which "height" variable will be assigned to in the following code?
int height; 
class Screen {
public:
typedef std::string::size_type pos;
void setHeight(pos);
pos height = 0; 
};
Screen::pos verify(Screen::pos);
void Screen::setHeight(pos var) {
height = verify(var);
}
A
int height; 
// Defines a name subsequently used inside Screen.
class Screen {
public:
typedef std::string::size_type pos;
void setHeight(pos);
pos height = 0; 
// This hides the declaration of height in the outer scope.
};
Screen::pos verify(Screen::pos);
void Screen::setHeight(pos var) {
// var: refers to the parameter
// height: refers to the class member
// verify: refers to the global function
height = verify(var);
// This will assign to the height variable in the class definition.
}
66
Q
HARD: Explain the following code, indicating which definition of Type or initVal is used for each use of those names. Say how you would fix any errors.
typedef string Type;
Type initVal();
class Exercise {
public:
typedef double Type;
Type setVal(Type);
Type initVal();
private:
int val;
};
Type Exercise::setVal(Type parm) 
{
val = parm + initVal();
return val;
}
A
typedef std::string Type;
Type initVal();
class Exercise {
public:
typedef double Type;
Type setVal(Type);
Type initVal();
private:
int val;
};
Type Exercise::setVal(Type parm) 
// Return type is will not match its declaration; should be preceded by "Exercise::"
{
val = parm + initVal();
return val;
}
// The function initVal was not defined but is called inside setVal(...) (above). Defined below using the correct return type.
Exercise::Type Exercise::initVal()
{
    return 0;
}
67
Q

The code below defines the constructor of Sales_data.
What is the difference between

Sales_data::Sales_data(const string &s,
unsigned cnt, double price) :
bookNo(s), units_sold(cnt), revenue(cnt * price)
{}

and the following?

Sales_data::Sales_data(const string &s,
unsigned cnt, double price)
{
bookNo = s;
units_sold = cnt;
revenue = cnt * price;
}
A
// This version initialises the data members of Sales_data.
Sales_data::Sales_data(const string &s,
unsigned cnt, double price) : 
bookNo(s), units_sold(cnt), revenue(cnt * price) 
{}
// This version assigns values to the data members of Sales_data. (Remember that member data is default initialised before the constructor body is executed if the initialiser list is empty.)
Sales_data::Sales_data(const string &s,
unsigned cnt, double price)
{
bookNo = s;
units_sold = cnt;
revenue = cnt * price;
}
68
Q

When might the use of a constructor initialiser list be necessary?

A

When the class possesses members which are const or references (two cases when initialisation of a variable is mandatory).

69
Q
Where is the error in the following code?
class ConstRef {
public:
ConstRef(int ii)
{ 
i = ii; 
ci = ii;
ri = i; 
}
private:
int i;
const int ci;
int &ri;
};
A
class ConstRef {
public:
ConstRef(int ii)
{
i = ii;
ci = ii; 
// This is an error; we cannot assign to a const.
ri = i; 
// This is an error; ri was never initialized.
}
private:
int i;
const int ci;
int &ri;
};
70
Q

In what order are class members initialised using a given constructor initialiser list?

A

In the order that they appear in the class definition (which may not be the order that they appear in the initialiser list).

71
Q

Can a constructor that contains a nonzero parameter list also be a default constructor?

A

Yes, if it supplies default arguments for every parameter.

72
Q

The following initialiser is in error. Identify and fix the problem.
struct X {
X (int i, int j): base(i), rem(base % j) { }
int rem, base;
};

A
struct X {
X (int i, int j): base(i), rem(base % j) { }
int rem, base;
// This is the error; rem appears first in the class definition so the compiler will try to initialise it first using the value of base, which has not yet been set.
};
73
Q

Would it be legal for both a constructor that takes a string and one that takes an istream& to have default arguments? If not, why not?

A

No, it is not legal, as this would lead to two default constructors.

74
Q

Can a constructor call another constructor? If so, how?

A

Only after C++11. A constructor can forward a call to another constructor through its constructor initialiser list.

75
Q

(C++11:) What is the name of a constructor that calls another constructor in its initialiser list?

A

A “delegating constructor”.

76
Q

How many entries does a delegating constructor have in its initialiser list?

A

Only one; the call to another constructor.

77
Q

The default constructor is used automatically whenever an object is default or value initialised. In what three cases might default initialisation occur?

A

(i) When we define nonstatic variables or arrays at block scope without initialisers.
(ii) When a class that itself has members of class type uses the synthesised constructor.
(iii) When members of class type are not explicitly initialised in a constructor initialiser list.

78
Q

The default constructor is used automatically whenever an object is default or value initialised. In what three cases might value initialisation occur?

A

(i) During array initialisation when we provide fewer initialisers than the size of the array.
(ii) When we define a local static object without an initialiser.
(iii) When we explicitly request initialisation by writing an expression of the form T() where T is the name of a type. (For example, the vector constructor that takes a single argument to specify the vector’s size uses an argument of this kind to value initialise its element initialiser.)

79
Q
Are there any problems with the following code?
class NoDefault {
public:
NoDefault(const std::string&);
};
struct A { 
NoDefault my_mem;
};
A a;
struct B {
B() {}
NoDefault b_member;
};
A
class NoDefault {
public:
NoDefault(const std::string&);
};
struct A { 
NoDefault my_mem;
};
A a; 
// This is an error; the compiler will be unable to synthesise a constructor for A as there is no default constructor for NoDefault.
struct B {
B() {} 
// This is an error; there is no initializer for b_member.
NoDefault b_member;
};
80
Q
Which of the following two statements correctly calls the default constructor of Sales_data?
Sales_data obj(); 
Sales_data obj2;
A
Sales_data obj(); 
// Incorrect; this declares a function, not an object.
Sales_data obj2; 
// Correct; obj2 is an object, not a function.
81
Q

Which, if any, of the following statements are untrue? Why?

(a) A class must provide at least one constructor.
(b) A default constructor is a constructor with an empty parameter list.
(c) If there are no meaningful default values for a class, the class should not provide a default constructor.
(d) If a class does not define a default constructor, the compiler generates one that initialises each data member to the default value of its associated type.

A
(a) A class must provide at least one constructor.
// Untrue; a class does not necessarily have to provide a constructor.
(b) A default constructor is a constructor with an empty parameter list.
// Untrue; a default constructor can have a nonempty parameter list, it just needs to have default arguments for each parameter.
(c) If there are no meaningful default values for a class, the class should not provide a default constructor.
// Untrue; a constructor should still be provided or other classes which default initialise objects of this type will not work.
(d) If a class does not define a default constructor, the compiler generates one that initialises each data member to the default value of its associated type.
// Untrue; the class must have no constructors otherwise the compiler will not generate a synthesised constructor.
82
Q

Every constructor that can be called with a single argument defines an implicit conversion to a class type. What is the name used for such a constructor?

A

A “converting constructor”.

83
Q

How many class-type conversions can a converting constructor make?

A

Only one. In general, a compiler will automatically apply one class-type conversion.

84
Q

How can the implicit conversion of an object through a converting constructor be avoided?

A

By preceding the constructor by the “explicit” keyword.

85
Q

When is the use of the “explicit” keyword meaningful?

A

When a constructor is a converting constructor, i.e. when the constructor only takes one argument.

86
Q

How must an “explicit” constructor be called?

A

By direct initialisation.

Note, the copy form of initialisation (i.e. using an “=”) will not work.

87
Q

What is the name given to a class that has all public members, no constructors, no in-class initialisers and no base or virtual classes?

A

An “aggregate class”.

88
Q

What is an “aggregate class”?

A

An aggregate class is a class that has all public members, no constructors, no in-class initialisers and no base or virtual classes.

89
Q
Is the following struct an aggregate class?
struct Data {
int ival;
string s;
};
A

Yes, Data is an aggregate class.

90
Q

Can the members of an aggregate class be provided initialisers despite having no constructors?

A

Yes, using a braced list. The initialisers in the braced list must be in the order that the members of the aggregate class appear.

91
Q

What happens if a braced list used to initialise the members of an aggregate class does not contain as many initialisers as there are members?

A

As with initialisation of array elements, if the list of initialisers has fewer elements than the class has members, the trailing members are value initialised.

92
Q

What is the term used to refer to an aggregate class that contains only data members of literal type?

A

A “literal class”.

93
Q

What restrictions must an aggregate class meet to be a literal class?

A
  • The data members must all have literal type.
  • The class must have at least one constexpr constructor.
  • If a data member has an in-class initialiser, the initialiser for a member of built-in type must be a constant expression, or if the member has class type, the initialiser must use the member’s own constexpr constructor.
  • The class must use default definition for its destructor, which is the member that destroys objects of the class type.
94
Q

Describe a typical constexpr constructor.

A

A constructor has no return type and the only executable statement in a constexpr function is a return statement. Thus, a constexpr constructor typically has an empty body.

A constexpr constructor must initialise every data member. The initialisers must either use a constexpr constructor or be a constant expression.

95
Q

How does a member become associated with the class, rather than each individual object of that class?

A

By preceding its type specifier by the “static” keyword.

96
Q

True or false? The static members of a class exist outside any object.

A

True.

97
Q

When can the body of a static member function use a “this” pointer?

A

Never. A static class member is not bound to any individual object, so it does not have a this pointer.

98
Q
Will the following code compile?
class Account {
public:
static void calculate(double a,double b) const { a+=a*b; }
};
A
No, it will not compile. A static member is not associated with an object so it cannot be made const.
class Account {
public:
static void calculate(double a,double b) const { a+=a*b; }
};
99
Q

What is the problem with the following code?
class Account {
public:
static void calculate(double a) { destroy(a); }
void destroy(double a) { a=0; }
};

A

A static member function is not associated with any object, so it cannot call a nonstatic member function. This would implicitly use a “this” pointer.

100
Q

How can a static member function be called?

A

Without a class object, it can be called using the scope operator, “::”. It can also be accessed using the dot or arrow operator (through a class object or a pointer to a class object).

101
Q
Is there an error with the following code?
class Account {
public:
void calculate() { amount += amount * interestRate; }
private:
static double interestRate;
// remaining members as before
};
A

There is no error in the code below. Note that a member function can use a static member without the scope operator.

class Account {
public:
void calculate() { amount += amount * interestRate; }
private:
static double interestRate;
// remaining members as before
};
102
Q
Will the following code compile?
class Account {
public:
static double rate() { return interestRate; }
private:
static int interestRate = 30;
};
A

class Account {
public:
static double rate() { return interestRate; }
private:
static int interestRate = 30;
// This is an error; a nonconst static member cannot be initialised inside the class body.
};

103
Q
Pinpoint the error in the following code.
class Account {
public:
static void rate(double newRate);
private:
static int interestRate;
};
int Account::interestRate=30;
void Account::rate(double newRate) 
{
interestRate=newRate;
}
A
class Account {
public:
static void rate(double newRate);
private:
static int interestRate;
};
int Account::interestRate=30;
void Account::rate(double newRate) 
{
interestRate=newRate;
// This is an error; cannot use interestRate before it is initialised.
}
104
Q
Where is the error in the following code?
class Account {
public:
static void rate(double newRate);
private:
static int interestRate;
};
int Account::interestRate=30;
static void Account::rate(double newRate) 
{
interestRate=newRate;
}
A
Where is the error in the following code?
class Account {
public:
static void rate(double newRate);
private:
static int interestRate;
};
int Account::interestRate=30;
static void Account::rate(double newRate) 
// The definition of a static member function outside the class must not repeat the static keyword; it should only appear inside the class body with the declaration.
{
interestRate=newRate;
}
105
Q

What is the problem with the following code, if any?
class Account {
public:
Account(double newRate) {interestRate=newRate;}
private:
static int interestRate;
};

A

class Account {
public:
Account(double newRate) {interestRate=newRate;}
// This is an error; static data member cannot be initialised through the class’ constructor.
private:
static int interestRate;
};

106
Q

True or false? Although static member data is not associated with a class, it can still be initialised through the class’ constructors.

A

False. Static member data cannot be initialised through the class’ constructors.

107
Q
Will the following code compile?
class Account {
public:
Account(double newRate) : interestRate(newRate) {}
private:
static double interestRate;
};
A
No, the code will not compile.
class Account {
public:
Account(double newRate) : interestRate(newRate) {}
// A static member variable can only be initialised through its definition. 
private:
static double interestRate;
};
108
Q

Why can static member data not be initialised by a class’ constructor?

A

Because static data members are not part of individual objects of the class type. Thus, they are not defined when we create objects of the class.

109
Q

How can nonconst static member data be initialised?

A

It must be initialised when it is defined outside the class body.

110
Q

How can const static member data be initialised?

A

If the static member data has const integral type, it can be initialised using an in-class initialiser. If it is a constexpr of literal type, it must be initialised using an in-class initialiser.

111
Q

When must static data members be initialised using an in-class initialiser?

A

When they are constexprs of literal type.

112
Q
Will the following code compile?
class Account {
public:
static double rate() { return interestRate; }
static void rate(double);
private:
static constexpr int period = 30;
double daily_tbl[period];
};
A
Yes, although period is static member data, it has const integral type, so it can be initialised using an in-class initialiser.
class Account {
public:
static double rate() { return interestRate; }
static void rate(double);
private:
static constexpr int period = 30;
double daily_tbl[period];
};
113
Q

When does an initialised const or constexpr static data member not need to be separately defined?

A

When the member is used only in contexts where the compiler can substitute the member’s value.

However, if we use the member in a context in which the value cannot be substituted, then there must be a definition for that member.

114
Q

Is it a good idea to always define const static member data outside the class body?

A

Yes. Although an initialised const or constexpr static does not need to be separately defined if it is only used in contexts where the compiler can substitute the member’s value, it does otherwise.

115
Q
Where is the error in the following code?
class Bar {
public:
// . . .
private:
static Bar mem1;
Bar *mem2; 
Bar mem3;
};
A

class Bar {
public:
// . . .
private:
static Bar mem1;
// This is okay; a static member can have incomplete type.
Bar *mem2;
// This is okay; a pointer member can have incomplete type.
Bar mem3;
// This is an error; data members must have complete type.
};

116
Q
Will the following code compile?
class Screen {
public:
Screen& clear(char = bkground);
private:
static const char bkground;
};
A

Yes. Note that static member data can be used as a default argument.

class Screen {
public:
Screen& clear(char = bkground);
private:
static const char bkground;
};
117
Q

List (up to four) advantages of static members.

A

(1) Storage efficient.
(2) If a static member of a class changes, each object of the class will use the new value of that static member.
(3) A static data member can have incomplete type.
(4) A static member (either a data member or a member function) can be used as a default argument.

118
Q

What is a difference between ordinary members and static members?

A

A static member belongs to the class, an ordinary member belongs to objects of the class.

119
Q
Which, if any, of the following static data member declarations and definitions are errors? Explain why.
// example.h
class Example {
public:
static double rate = 6.5;
static const int vecSize = 20;
static vector vec(vecSize);
};
// example.C
#include "example.h"
double Example::rate;
vector Example::vec;
A
// example.h
class Example {
public:
static double rate = 6.5;
// This is an error; nonconst static member data should be initialised outside the class.
static const int vecSize = 20;
static vector vec(vecSize);
// There are two problems here: (i) nonconst static member data cannot be initialised inside a class, and; (ii) we cannot use parentheses as in-class initialiser (it will be mistaken for the declaration of a function).
};
// example.C
#include "example.h"
double Example::rate;
// Should initialise static data member.
vector Example::vec;
// Should initialise static data member.
120
Q

Is it possible to create a class from which we cannot create any objects?

A

Yes, by creating a private constructor.

121
Q

What is a “class”?

A

A C++ mechanism for defining our own abstract data types.