Classes Flashcards
Chapter 7
When does a const member assume its constness in an object’s lifecycle
Unlike other member functions, constructors may not be declared as const. When we create a const object of a class type, the object does not assume its “constness” until after the constructor completes the object’s initialization. Thus, constructors can write to const objects during their construction.
How can we ask compiler to provide a default constructor
struct Data
{
Data() = default;
};
How to change a const data member
By including mutable keyword class Screen { public: void some_member() const; private: mutable size_t access_ctr; // may change even in a const object // other members as before }; void Screen::some_member() const { \++access_ctr; // keep a count of the calls to any member function // whatever other work this member needs to do }
Is friend-ship transtive
It is important to understand that friendship is not transitive. That is, if class Window_mgr has its own friends, those friends have no special access to Screen.
Does defining a friend function inside a class work?
No Even if we define the function inside the class, we must still provide a declaration outside of the class itself to make that function visible. A declaration must exist even if we only call the friend from members of the friendship granting class:
struct X { friend void f() { /* friend function can be defined in the class body */ } X() { f(); } // error: no declaration for f void g(); void h(); }; void X::g() { return f(); } // error: f hasn't been declared void f(); // declares the function defined inside X void X::h() { return f(); } // ok: declaration for f is now in scope
Are class members and functions and member process ( or parsed ) by compiler in the same phase
Class definitions are processed in two phases: • First, the member declarations are compiled. • Function bodies are compiled only after the entire class has been seen.
Can a class redefine an outer scope typedef into an inner scope one
In a class, if a member uses a name from an outer scope and that name is a type, then the class may not subsequently redefine that name:
typedef double Money;
class Account {
public:
Money balance() { return bal; } // uses Money from the outer scope
private:
typedef double Money; // error: cannot redefine Money
Money bal;
// …
};
It is worth noting that even though the definition of Money inside Account uses the same type as the definition in the outer scope, this code is still in error.
In which order are members initialized in a class
Members are initialized in the order in which they appear in the class definition: The first member is initialized first, then the next, and so on. The order in which initializers appear in the constructor initializer list does not change the order of initialization.
What are delegating constructors
The new standard extends the use of constructor initializers to let us define so-called delegating constructors. A delegating constructor uses another constructor from its own class to perform its initialization. It is said to “delegate” some (or all) of its work to this other constructor.
class Sales_data { public: // nondelegating constructor initializes members from corresponding arguments Sales_data(std::string s, unsigned cnt, double price): bookNo(s), units_sold(cnt), revenue(cnt*price) { } // remaining constructors all delegate to another constructor Sales_data(): Sales_data("", 0, 0) {} Sales_data(std::string s): Sales_data(s, 0,0) {} Sales_data(std::istream &is): Sales_data() { read(is, *this); } // other members as before };
Default initialization VS Value initialization
The default constructor is used automatically whenever an object is default or value initialized. Default initialization happens • When we define nonstatic variables (§ 2.2.1, p. 43) or arrays at block scope without initializers • When a class that itself has members of class type uses the synthesized default constructor • When members of class type are not explicitly initialized in a constructor initializer list
Value initialization happens
• During array initialization when we provide fewer initializers than the size of the array
• When we define a local static object without an initializer
• When we explicitly request value initialization by writing an expressions of the form T() where T is the name of a type (The vector constructor that takes a
single argument to specify the vector’s size uses an argument of this kind to value initialize its element initializer.)
How to initialize an object with default constructor
Without using ()
Sales_data obj(); // oops! declares a function, not an object Sales_data obj2; // ok: obj2 is an object, not a function
Refer Most vexing parse
How many level conversion will compiler apply when for class conversion
Only One Class-Type Conversion Is Allowed
In we noted that the compiler will automatically apply only one class-type conversion. For example, the following code is in error because it implicitly uses two conversions:
// ERROR: requires two user-defined conversions: // (1) convert "9-999-99999-9" to string // (2) convert that (temporary) string to Sales_data item.combine("9-999-99999-9");
If we wanted to make this call, we can do so by explicitly converting the character string to either a string or a Sales_data object:
// ok: explicit conversion to string, implicit conversion to Sales_data
item.combine(string(“9-999-99999-9”));
// ok: implicit conversion to string, explicit conversion to Sales_data
item.combine(Sales_data(“9-999-99999-9”));
Whats the use of explicit keyword infront of ctor declaration
We can prevent the use of a constructor in a context that requires an implicit conversion by declaring the constructor as explicit:
class Sales_data { public: Sales_data() = default; Sales_data(const std::string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) { } explicit Sales_data(const std::string &s): bookNo(s) { } explicit Sales_data(std::istream&); // remaining members as before };
What is an aggregate class
An aggregate class gives users direct access to its members and has special initialization syntax. A class is an aggregate if • All of its data members are public • It does not define any constructors • It has no in-class initializers • It has no base classes or virtual functions
struct Data {
int ival;
string s;
};
Data val1 = { 0, “Anna” };
The initializers must appear in declaration order of the data members.
What is a litral class
An aggregate class whose data members are all of literal type is a literal class.
A nonaggregate class, that meets the following restrictions, is also a literal class: • The data members all must have literal type. • The class must have at least one constexpr constructor. • If a data member has an in-class initializer, the initializer for a member of builtin type must be a constant expression, or if the member has class type, the initializer 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.
A constexpr constructor must initialize every data member. The initializers must either use a constexpr constructor or be a constant expression.