notes/c++.md

39 lines
2.3 KiB
Markdown
Raw Normal View History

2024-05-10 12:03:13 +02:00
---
title: C++
---
# C++
## Why `operator[]` returns a reference
```c++
class IntList
{
private:
int m_list[10]{};
public:
int& operator[] (int index);
};
int& IntList::operator[] (int index)
{
return m_list[index];
}
```
Lets take a closer look at how `list[2] = 3` evaluates. Because the subscript operator has a higher precedence than the assignment operator, `list[2]` evaluates first. `list[2]` calls `operator[]`, which is defined to return a reference to `list.m_list[2]`. Because `operator[]` is returning a reference, it returns the actual `list.m_list[2]` array element. The partially evaluated expression becomes
`list.m_list[2] = 3`, which is a straightforward integer assignment.
Any value on the left hand side of an assignment statement must be an l-value (which is a variable that has an actual memory address). Because the result of `operator[]` can be used on the left hand side of an assignment (for example `list[2] = 3`), the return value of `operator[]` must be an l-value. As it turns out, references are always l-values, because you can only take a reference of variables that have memory addresses. So by returning a reference, the compiler is satisfied returning an l-value.
Consider what would happen if `operator[]` returned an integer by value instead of by reference. `list[2]` would call `operator[]`, which would return the value of `list.m_list[2]`. For example, if `m_list[2]` had the value of 6, `operator[]` would return the value 6. `list[2] = 3` would partially evaluate to `6 = 3`, which makes no sense. If you try to do this, the C++ compiler complains:
C:VCProjectsTest.cpp(386) : error C2106: '=' : left operand must be l-value
Taken from [Overloading the Subscript Operator](https://www.learncpp.com/cpp-tutorial/overloading-the-subscript-operator/).
### Necessity of a virtual destructor for an abstract class
A virtual destructor is essential for an abstract class because an object of a derived class is usually manipulated through the interface provided by its abstract base class. In particular it may be deleted through a pointer to a base class. Then the virtual function call mechanism ensures that the proper destructor is called. That destructor then implicitly invokes the destructors of its bases and members.