Contents:
Introduction
Questions
Object
Creation
Virtual
Methods and Inheritance
Trait
Classes
Values,
References, and Constant References
Answers
Object
Creation
Virtual
Methods and Inheritance
Trait
Classes
Values,
References, and Constant References
The implementation of FreePOOMA uses many advanced or obscure features of the ANSI/ISO C++ standard. Its interface is less exacting, but programmers must still have a solid understanding of C++ to use it effectively. If you feel comfortable with the questions below, and their answers, you should have little or no difficulty using FreePOOMA. If, on the other hand, you find the questions and their answers difficult, you may wish to look at some of the books in the recommended reading before trying to use this library.
Fred red;
Fred func(
Fred cyan
){
Fred magenta;
magenta = cyan;
return magenta;
}
int main()
{
Fred green = red;
blue = func(green);
return 0;
}
What does the following program print out?
#include <iostream>
#include <iomanip>
using namespace std;
class A
{
public :
A() { cout << "A new" << endl; }
virtual void left() { cout << "A left" << endl; }
void right() { cout << "A right" << endl; }
};
class B : public A
{
public :
B() { cout << "B new" << endl; }
void left() { cout << "B left" << endl; }
void right() { cout << "B right" << endl; }
};
int main()
{
A a;
a.left();
a.right();
cout << endl;
B b;
b.left();
b.right();
cout << endl;
A * ap = &b;
ap->left();
ap->right();
cout << endl;
A * ap = (A*)&b;
ap->left();
ap->right();
cout << endl;
ap->A::left();
((A*)ap)->left();
((A*)ap)->right();
return 0;
}
What does the following program print out?
class Blue
{
public :
enum { Val = 240; };
};
template<class T>
class Green
{
public :
const int Val = 88;
};
template<class T>
class Red
{
public :
enum { Val = T::Val/2; };
};
int main()
{
cout << Blue::Val << endl;
cout << Green<Blue>::Val << endl;
cout << Red<Blue>::Val << endl;
cout << Red<Green<Blue>>::Val << endl;
cout << Red<Green<Green<Blue>>>::Val << endl;
cout << Red<Red<Green<Blue>>>::Val << endl;
return 0;
}
Which of the calls to value(), reference, and const_reference below produce errors during compilation?
void value(int x)
{}
void reference(int & x)
{}
void const_reference(const int & x)
{}
int main()
{
int x;
const int y = 2;
value(1);
value(x);
value(y);
value(x+1);
reference(1);
reference(x);
reference(y);
reference(x+1);
const_reference(1);
const_reference(x);
const_reference(y);
const_reference(x+1);
return 0;
}
The listing below shows where constructor calls and assignments occur:
Fred red; // default constructor
Fred func(
Fred cyan // copy constructor
// (pass by value)
){
Fred magenta; // default constructor
magenta = cyan; // assignment operator
return magenta; // copy constructor
// (magenta is copied into
// a nameless temporary to
// be returned)
}
int main()
{
Fred green = red; // copy constructor
blue = func(green); // copy constructor twice
// ('green' is copied into
// 'cyan' during call, and
// temporary return value
// is copied into 'blue' on
// exit)
return 0;
}
The program prints the following:
A new // A::A()
A left // A::left()
A right // A::right()
A new // B::B() invokes A::A()
B new // body of B::B()
B left // B::left()
B right // B::right()
B left // left() is virtual
A right // right() is not virtual
B left // cast on right irrelevant
A right // right() is not virtual
A left // exact method named
B left // cast on left irrelevant
A right // right() is not virtual
The key here is that Green always defines its own Val, while Red defines its Val in terms of its argument class's Val. The answer is therefore:
int main()
{
cout << Blue::Val << endl; // 240
cout << Green<Blue>::Val << endl; // 88
cout << Red<Blue>::Val << endl; // 120
cout << Red<Green<Blue>>::Val << endl; // 44
cout << Red<Green<Green<Blue>>>::Val << endl; // 44
cout << Red<Red<Green<Blue>>>::Val << endl; // 22
return 0;
}
The only outright errors occur when a constant value (such as a literal or the result of an arithmetic expression) is passed where a non-constant reference parameter is expected. There is also a warning when x is used before being assigned a value:
int main()
{
int x;
const int y = 2;
value(1);
value(x); // Warning, value used before set.
value(y);
value(x+1);
reference(1); // Error. Non-const reference to const.
reference(x);
reference(y); // Error. Non-const reference to const.
reference(x+1); // Error. Non-const reference to const.
const_reference(1);
const_reference(x);
const_reference(y);
const_reference(x+1);
return 0;
}