COMP6771, Tutorial - Week 4 COMP6771– Advanced C++ Programming Session 2, 2016 Tutorial – Week 4 Aims This tutorial will give you a chance to practice working with C++ classes, including constructors, copy control, friends and lvalue and rvalue references. The questions cover the material from Chapters 12 and 13 of your textbook. Tutorial Questions Classes facilitate abstraction and encapsulation. Describe these two important concepts. A forward class declaration declares an incomplete type. What does this mean? Can an incomplete type be used to define objects? Can it be used to define anything at all? What about in C and Java? Can a class have data members of its own type? Why/why not? Once a name has been used as a type, it may not be redefined. Which one of the following objects is invalid according to this rule?
typedef int my_type;
class X {
typedef double my_type;
my_type a;
};
class Y {
my_type a;
typedef double my_type;
};
Explain the following code. Indicate which definition of Type or initVal is used for each instance of those names. If there are any errors, say how you would fix the program.
typedef int Type;
Type initVal() {
return 0;
}
class Exercise {
public:
typedef double Type;
Type setVal(Type);
Type initVal();
private:
Type val;
};
Type Exercise::setVal(Type parm) {
val = parm + initVal();
return val;
}
The definition of the member function setVal is in error. Apply the necessary changes so that it uses the correct Type and calls the global instance of initVal. What is the function of class constructors? What is a default constructor? What is a synthesised default constructor? What is a constructor initialiser list? Explain, by referring to the two C++ constructor phases, why using the initialiser list is more efficient than value assignment in the constructor body. What situations require the use of the constructor initialiser list? How can constructors be used to define implicit type conversions? Give an example. Do all class constructors define implicit type conversions? How would you specify that a constructor is not to be used in implicit type conversions? Do friends violate ecapsulation? What must be added to the following code to make it valid?
class X {
friend class Y;
friend void f() { return; }
};
class Z {
Y *ymem;
void g() { return ::f(); }
};
What properties of class types and friend functions are highlighted in this code example? Describe the special properties of integral static const data members? What is the difference between value semantics and reference semantics? In C++, what are the Big Three/Five operations of copy control? When is explicit copy control likely to be required? Consider the following value-like class defined in Section 13.2.1:
=======================
HasPtrValueLike.h
=======================
#include
// value-like implementation of HasPtr
class HasPtr {
friend void swap(HasPtr&, HasPtr&);
public:
HasPtr(const std::string &s = std::string()):
ps(new std::string(s)), i(0) { }
// each HasPtr has its own copy of the string to which ps points
HasPtr(const HasPtr &p):
ps(new std::string(*p.ps)), i(p.i) { }
HasPtr& operator=(const HasPtr &);
~HasPtr() { delete ps; }
private:
std::string *ps;
int i;
};
void swap(HasPtr &lhs, HasPtr &rhs);
=======================
HasPtrValueLike.cpp
=======================
#include
#include "HasPtrValueLike.h"
inline
void swap(HasPtr &lhs, HasPtr &rhs)
{
using std::swap;
swap(lhs.ps, rhs.ps); // swap the pointers, not the string data
swap(lhs.i, rhs.i); // swap the int members
}
using std::string;
HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
auto newp = new string(*rhs.ps); // copy the underlying string
delete ps; // free the old memory
ps = newp; // copy data from rhs into this object
i = rhs.i;
return *this; // return this object
}
Define the move constructor and move assignment operator for this class. Indicate the modifications to be made to the interface as well.