Essential C++ # 04. Object-Based Programming

C++

Chapter 4. Object-Based Programming

📌What should a class consist of?

A class consists of 2 parts:

  • public set of operations and operators (also called member functions which represents the public interface of the class)
  • private implementation

 

📌Why Class is important to C++?

Designing and implementing classes are the primary activities of C++ programmers.

 

4.1. Implement a Class

The following section will include some codes which mimic the behavior of stack(computer).

📌Class definition in C++

Things to noticed:

1️⃣ all functions must be declared inside public if you want to use with an instance. e.g. bool push/pop/peek/empty/full

2️⃣ functions declared+defined inside the class definition is inline function. e.g. int size()

 

📌Implement Class Definition

For those non-inline member functions, they are defined within a program text file. Normally suffix with .cpp, .c, .cc

The preceding syntax :: is called the class scope operator.

 

📌Conclusion of .h and .cpp

Header file .h contains:

  • the definition of the class
  • the declaration of public and private functions
  • if the function is also defined here, it is inline function

Program text file .cpp contains:

  • implement the function declare in .h
  • use inline keyword the specify the function to be an inline function

 

4.2. Constructor and Destructor

📌Regular Constructor in C++

Suppose we have a Person class. (eheww... Again it is Person class🙂)

 

📌Default Constructor

From my perspective, I think there are 2 ways of default constructors.

1️⃣No arguments, pure pure pure default constructor.

2️⃣Constructor with arguments with default values

 

📌Unusual Initialization

For a C# programmer, the following initialization is kind of...🤣

 

📌Member Initialization List

Suppose you have the following:

You can use member initialization list to construct as followed:

 

📌Why do we need Member Initialization List?

OK, now you can smell a bit about member initialization list. But why should we use it?🤔

What is the difference in the preceding codes??🤔😵

The difference is that ver1 only initialize once!!! Therefore, you should use member initialization list for performance benefits sake!

The preceding code I make 2 constructors. And suppose License instance is a member of Person.

1️⃣Not using member initialization list❌

The output:

You see the License instance is init once in the member list and init second times in the Person constructor.

2️⃣Using member initialization list✔

The output:

 

📌Use of Destructor

The primary use of a destructor is to free resources. The destructor cannot be reloaded!

 

📌When should we use destructor?

When the data members are store by value, there is no need to use destructor.

 

📌Difference of class between C++ and C#⭐

Everything works fine here. But!⚠⚡ The class is so heck different from class in C#.

The preceding code demonstrates that the class in C++ is not "reference type" in C#. The following is C#.

 

📌The Mechanism Behind the Difference between C++ and C#

In the preceding code, we are realized that the class is copy by value. (Yes and No...) The truth is that only the "value type" are pass by value!

The line Matrix mat2 = mat2; indicates that:

⚠⚠⚠!!! Serious shit happens here!!! When the destructor applied to mat2, the _pmat is deallocated and mat1 can't use it!!

 

📌Define a Full Copy Constructor

 

📌No Absolute Correct Way Designing a C++ Class

In the preceding, you see that C++ class are with more freedom to do so. While in C#, the instance is only reference type. When we design a class, we must ask ourselves whether the default member-wise behavior is adequate for the class?

  • If yes🙂, we need not provide an explicit copy constructor.
  • If not🙁, we MUST define an explicit instance and within it implement the correct initialization semantics.

 

4.3. mutable and const

📌const in Function Declaration

In short, a const function ensures the body code would NOT CHANGE the data member of the class.

 

📌Example of const and non-const Function

Suppose you have a class, the class is sort of storing data members. And you can maintain and read the data inside of it by next. (You know what it is..)

OK, let's take a look here.

 

📌How does the Compiler check if it ACTUALLY is const?

In short, the compiler will look at the function which is decorated with const. And check every functions inside that function if it is decorated with const....

 

This is a const function and it can be compiled.✔ Because every member function here is const.

 

This is NOT a const function and it cannot be compiled.❌Because it modifies the member.

 

📌Class Designer MUST consider the "constness"

The class designer must tell the compiler by labeling as const each member function that does not modify the class object.

 

📌const keyword should be both in declaration and definition

Please notice that the const is appear in both .h and .cpp files.

 

📌A Complicated Example

The following code will be compiled with errors.

TODO - Understand why.

The correct one should be this:

 

📌What is mutable?

In English, mutable is defined as:

mutable: able or likely to change

In C++, we decorate member acted as iterator to mutable. For example, the _next variable. Therefore, the Triangular class can be modified as followed:

With decorated mutable, the const function now can be compiled with no error!✔ (even though the _next is modified...)

 

4.4. this Pointer

📌What is this keyword?

In C#, this refer to the current instance of such class. There is no difference in C++. It also points to the current instance. Suppose we have a deep copy function to copy the Triangular object.

Few things need to be noticed: different meanings of &

  • 1️⃣Triangular& in the return type means the function is to return who else called this function.⭐⭐⭐ The & here means pass the object invoked by reference.1
  • 2️⃣&rhs in the function declaration means the rhs is pass by reference (speed up)
  • 3️⃣&rhs in the control flow means taking the address of rhs and compared with this.

 

📌Other Examples

1️⃣this cannot be assigned🙅‍♂️

The following method is designed to change current object to point to d object. It is with ERROR.❌

2️⃣this cannot be used in static function🙅‍♂️

The this can only exist in an instance.(class object)

3️⃣cannot use after delete🙅‍♂️

You can release manually by calling a function. (like GC in C#)

4️⃣Don't forget to & return type if you want to modify itself

The following is a bad example.

The result is:

But if we modify the function to:

The output is correct:

 

 

4.5. static Class Member

📌static in C++

The declaration and definition of static functions and members(fields) are both explicitly and separately.

Suppose you have a member static vector<int> and a function static bool is_elem(int):

The preceding is just the declaration. You have to define it:

1️⃣Either in Triangular.h like so:

2️⃣Or in Triangular.cpp like so:

 

📌static stuffs example

It's very much the same as with C#.

You can use it as the following:

 

📌static in C++ and C#

It is interesting to see the common and difference between these 2 languages.

 C++C#
Declarationin classin class
Definitionmust outside of class declaration(outside of the class {})can also in class declaration
Access Modifier::.

 

4.6. Iterator Class

Finally! We are going to implement our own iterator class!

 

📌User Story on Iterator

Iterate the Triangular sequence using iterator.

 

📌First Look on Iterator

//TODO What is operator* exactly?

📌Equality and Inequality as an Example

1️⃣ Let's implement the == operator first:

The _index is exactly for checking equality. Therefore, the code could be something like the following:

For a better format and indentation:

The this pointer implicitly represents the left operand.

2️⃣ The following is the example of how to use it

Why the pointers require dereference?🤔 Please take a look at the function declaration! It's because the type is Triangular_iterator!

3️⃣ Implement "inequality"

The complement of an operator is typically implemented with its associated operator2.

You see? It's so simple! 😍 Because in *this == rhs means:

  • dereference current object pointer
  • since lhs and rhs are both object
  • apply == operator
  • use ! to take its complement

 

📌Things to Notice when Overloading Operators🙅‍♂️

1️⃣There are 4 operators that can't be overloaded:

  • .
  • .*
  • ::
  • ?:.

2️⃣The arity of existing operator can't be overloaded

For example, if you overloaded == operator, then you must put 2 operands.

3️⃣ At least 1 class type as argument

We cannot refine operators for nonclass types, e.g. pointers.

4️⃣ The precedence can't be overwritten

e.g. / always takes precedence over +

 

📌Difference between member operator and non-member operator

Member operator function:

Nonmember operator function:

//TODO - figure this out

 

📌Overload prefix and postfix

It means implementing:

  • prefix - ++it
  • postfix - it++

prefix:

postfix:

How does it work?

  • For prefix, the _index is implemented before accessing the _elem
  • For postfix, the _index is implemented after accessing the _elem

 

Please take a look the operator declaration:

The prefix has no parameter, postfix has parameter. Why?🤔 Because each overloaded operator MUST have a unique parameter list. The single int in postfix will be handled by the compiler. So no worries.

//TODO figure out why there should be a int& in prefix.

 

📌Nested Types

It uses typedef:

The existing_type can be built-in, compound, or class type. We can take advantage of this to implement the last piece of our iterator.

With the preceding implementation, we could access Triangular_iterator of Triangular object simply by iterator.

Because we typedef in Triangular class, therefore you have to use the class scope operator :: to access it. And that's the reason and mechanism behind the container class.

 

4.7. friend in C++

📌What is friend?

In short, it makes the collaboration between classes available! Friendship is generally required for performance reasons, such as the multiplication of a Point and Matrix in a nonmember operator function.

 

📌Friendship in Functions

With the preceding declaration, you can have the following:

 

📌Friendship in Class

Define Triangular_iterator as a friend in Triangular is more efficient.

 

4.8. Copy Assignment Operator

📌Use = to assign objectA to objectB

In 4.2. we mentioned that the following class cannot be copied easily.

The problem may occur in the following block of code:

While we can overload = operator to solve this problem.

Few things to notice:

  • 1️⃣ this != &rhs is to check the address are different
  • 2️⃣ //TODO I don't quite understand why should we delete [] _pmat
  • 3️⃣ In the end, return *this as itself to Matrix&
  • 4️⃣ Warning! The preceding implementation is not exception-safe.

 

4.9. Implementing a Function Object

📌What is Function Object?

It is a class that provides an overloaded instance of the function call operator.

 

📌Parameter List of Function Object

The function call operator can take any number of parameters: none, one, two, and so on.

 

📌Example: LessThan Function Class

You can define as the following:

You can use it like:

The example code would be like:

 

 

4.10. iostream operator for Class instance

📌ostream operator <<

The ostream operator is very much like the .ToString() member function in C#.

Few things to notice:

1️⃣ rhs is declared both with const and &. That is to speed up the process by pass by reference. And in the meantime, the rhs is not modified.

2️⃣ the return type ostream& is not declared with const since each output operation modifies the internal state of the ostream object.

3️⃣ the operator is not declared as member function. Why? Because a member function requires that its left operand be an object of that class.

 

📌istream operator >>

Input operators are more complicated to implement because of the possibility of invalid data being read!

 

 

 

 

 

 

 

 

 


1 因此,谁唤起的这个函数,就改变谁。Triangular&代表两件事,1.返回类型是Triangular, 2.&是改变自身。因此tri.Copy()正是改变自身(tri)
2 complement是数学的概念,如vector的complement就是covector。同理,==的complement就是!=。 一般这种成对出现的对象,都可以用其另一半完成~
Previous
Previous

Essential C++ # 05. Object-Oriented Programming

Next
Next

C# 06 Study Notes Errors and exceptions