350 likes | 463 Views
The Rest of the Story. Object Management. Object Management The Rest of the Story. Constructors Compiler-generated The Initializer List Copy Constructors Single-arg (conversion ctors) The Assignment Operator. Constructors. Execute after an object’s memory is allocated
E N D
The Rest of the Story Object Management
Object ManagementThe Rest of the Story • Constructors • Compiler-generated • The Initializer List • Copy Constructors • Single-arg (conversion ctors) • The Assignment Operator CS 3370 - C++ Software Development
Constructors • Execute after an object’s memory is allocated • Used to initialize an object’s memory • Which constructor executes depends on arguments passed • Run after sub-objects are initialized • Base classes and sub-objects initialize first • Example: initMembers.cpp CS 3370 - C++ Software Development
Initializing Member ObjectsDefault Behavior • Member objects are default-initialized • class types run the default constructor • built-in types are not initialized by default • See initInt.cpp, defaultinit.cpp • “Zero Initialization”: • Occurs with an explicit call to a default ctor • Even with built-ins: int x = int( ); // 0 • See defaultinit2.cpp CS 3370 - C++ Software Development
The Initializer List • By-passes default initialization • The only way to initialize const and reference members • It is inefficient and poor practice to initialize member objects in the body of the containing constructor • Built-in types are okay, though • Examples: badInit.cpp, goodInit.cpp, constMem.cpp CS 3370 - C++ Software Development
A Simple String ClassManages a char buffer #include <cstring> #include <iostream> class String { char* data; public: String(const char* s = "") { data = new char[std::strlen(s) + 1]; std::strcpy(data,s); } ~String() {delete [] data;} int size() const {return std::strlen(data);} char getAt(int pos) const {return data[pos];} void setAt(int pos, char c) const {data[pos] = c;} void display() { std::cout << data << '\n'; } }; CS 3370 - C++ Software Development
Using class String int main() { String s = "hello"; // same as String s("hello"); for (int i = 0; i < s.size(); ++i) cout << "s[" << i << "] == " << s.getAt(i) << std::endl; String empty; std::cout << '"'; empty.display(); std::cout << "\"\n"; } /* Output: s[0] == h s[1] == e s[2] == l s[3] == l s[4] == o "" */ CS 3370 - C++ Software Development
Strange Behavior int main() { String s = "hello"; String t = s; // same as String t(s); t.setAt(0,'j'); s.display(); } /* Output: jello a.out(4603) malloc: *** error for object 0x100100080: pointer being freed was not allocated */ CS 3370 - C++ Software Development
Initialization vs. Assignment • Initialization occurs only once, right after an object is created • always by some constructor • Assignment occurs only after an object has been initialized • via operator= • Which constructor executed in the previous slide? CS 3370 - C++ Software Development
The Copy Constructor • Initializes a new object as a copy of an existing object • of the same type or of some convertible type • Has signature T::T(const T&) • or T::T(T&) // not recommended • Copies each member across • using their own copy constructors, recursively • Generated by the compiler • But you can override it (and sometimes should) CS 3370 - C++ Software Development
Compiler-generated Copy Ctor String(const String& s) : data(s.data) {} // Identical here to: String(const String& s) { data = s.data; } (because pointers are not objects, and hence are not default-initialized.) CS 3370 - C++ Software Development
Shallow Copy s::data hello\0 t::data CS 3370 - C++ Software Development
Problems with Shallow Copy • If you have a pointer as a data member, a shallow copy is probably not what you want • Multiple pointers point to the same memory • If you de-allocate the data member in one object, you have created a likely fatal situation in the other (double delete) CS 3370 - C++ Software Development
Deep Copy • Classes with pointer members representing a dynamically allocated resource should offer a deep copy: • Allocate new heap space • Copy data to new target CS 3370 - C++ Software Development
A “Deep Copy” Copy Constructor String(const String& s) { data = new char[strlen(s.data)+1]; strcpy(data, s.data); } CS 3370 - C++ Software Development
Passing Objects by Value • Rarely done for non-built-in types • Objects are often returned by value, though • New values are often created • A copy is made • Therefore, a constructor executes • But which constructor? CS 3370 - C++ Software Development
Which Constructor? • Not always the copy constructor • Depends on the argument(s) • via overload resolution • As simple as that! • Example: trace.cpp CS 3370 - C++ Software Development
More Strange BehaviorAfter coding the Copy Constructor • Why does changing t affect s below? int main() { String s = "hello"; // same as String s("hello"); String t; t = s; t.setAt(0, 'j'); s.display(); } /* Output: jello a.out(4767) malloc: *** error for object 0x100100080: pointer being freed was not allocated */ CS 3370 - C++ Software Development
Object Assignment • Uses operator= • must be a member function • Generated by the compiler • assigns each data member individually • does a shallow copy • You can override it • and sometimes should, just like the copy constructor CS 3370 - C++ Software Development
Compiler-generated Assignment String& String::operator=(const String& rhs) { data = rhs.data; return *this; } s hello\0 t CS 3370 - C++ Software Development
What should String::operator=Do? • Allocate new heap space • Copy characters to target • Delete the old heap space • Return *this • Avoid unnecessary self-assignment • An optional but encouraged optimization • And watch the order you do things in! CS 3370 - C++ Software Development
Correct Assignment String& String::operator=(const String& s) { if (&s != this) // avoid self-copy { char* new_data = new char[strlen(s.data)+1]; strcpy(new_data, s.data); // copy delete [] data; // delete old data = new_data; // store new } return *this; // for full ass’t. semantics } CS 3370 - C++ Software Development
Prohibiting Copy and Assignment • A must for large objects (streams, etc.) • Make the copy constructor and assignment operator private • Will cause a compile error if client code tries to copy or assign • Only declare them • Define no function bodies • Will cause a link error if member functions try to copy or assign CS 3370 - C++ Software Development
Standard Conversions • Implicit promotion of numeric types • Widening of: • char -> short -> int -> long -> long long • Conversion from integer to floating-point • Needed in mixed-mode expressions (x + i) and in passing parameters • Function prototypes initiate the conversion for parms CS 3370 - C++ Software Development
Implicit Conversions to Class Type • You can allow conversions to and from any class type from or to any other type • Convert to a class type via a single-arg constructor • aka “conversion constructor” • Convert from a class type via a conversion operator • a special type of member function • You can turn off implicit conversions • With a special keyword (explicit) CS 3370 - C++ Software Development
Limitations • Sometimes multiple conversions occur invisibly in sequence in a single expression • Only one class type (i.e., non-primitive) is allowed inside a sequence of conversions • Example • convert.cpp • convert2.cpp CS 3370 - C++ Software Development
Turning off Implicit Conversions • explicit keyword • Example • convert3.cpp CS 3370 - C++ Software Development
Object Management Summary • Copy Constructor • the compiler generates a shallow one if you don’t define it • All Other Constructors • if you don’t provide any constructors at all, the compiler generates a default constructor (which default-constructs each member) • Single-arg constructors are conversion constructors • Assignment Operator • the compiler generates a shallow one if you don’t define it • Destructor • the compiler generates an empty one if you don’t define it • Members with destructors are destructed automatically anyway CS 3370 - C++ Software Development
const Correctness of Objects • const is your friend • It prevents modification errors by enforcing "read-only-ness" • const objects can only call constmember functions • all objects can call const member functions! • constmember functions receive the following this pointer: • const T * const this • Non-const member functions receive the following this pointer: • T * const this CS 3370 - C++ Software Development
const and mutable • const member functions cannot change fields: • “x = 2” “this->x = 2” // error in a const fn • Unless they’re mutable • “x = 2” “const_cast<T*>(this)->x = 2” • See mutable.cpp • Remember: const is a user-view thing CS 3370 - C++ Software Development
const-ness and Constructors • Objects don’t exist until they are fully initialized by a constructor • Constructors do not receive a this pointer • This if OK: you have to modify things during initialization! • So you don’t declare constructors const • Nor do they return anything CS 3370 - C++ Software Development
Overloading const • Consider front, back, and at in class Deque • They are non-const functions • They can’t be applied to a const Deque object • You can overload on const • So you can define overloaded const versions • See deque2.cpp and deque3.cpp • However, there is a problem with the return by reference! • Look at the return types of the const versions CS 3370 - C++ Software Development
const and Reference Returns • A const member function should never return a non-const reference • Remember, it’s a user-view thing • You are responsible to enforce this! • Always provide two overloads: • T& f( ); • const T& f() const; • Classical example: the indexing operator (same as at( )) • T& operator[](int pos); • const T& operator=(int pos) const; • See deque4.cpp CS 3370 - C++ Software Development
Initializing Static Data Members • Only the declaration goes in the class definition • Usually in a .h file • The definition of the member must occur at global scope • In a .cpp file • Defines space for the member in the data segment • (There is no “class object” in C++ like in other OO languages) CS 3370 - C++ Software Development
Defining a Static Pool ObjectFor Program 2 • In MyObject.h:class MyObject {static Pool pool;…}; • In MyObject.cpp:Pool MyObject::pool(…); CS 3370 - C++ Software Development