C++学习系列六:Classes(II)||overload operator||this||static members||const member functions||special membe

本文深入探讨了C++中运算符重载的概念,包括如何通过成员函数实现运算符重载,以及如何使用关键字this进行自我引用检查。此外,还介绍了静态成员、常量成员函数、类模板、特化、特殊成员函数等高级主题,以及继承和多态的基本原理。
  • Overloading operators

Classes, essentially, define new types to be used in C++ code. And types in C++ not only interact with code by means of constructions and assignments. They also interact by means of operators. For example, take the following operation on fundamental types:

int a, b, c;
a = b + c;

Here, different variables of a fundamental type (int) are applied the addition operator, and then the assignment operator. For a fundamental arithmetic type, the meaning of such operations is generally obvious and unambiguouse, but it may not be so for certain class types. For example :

struct myclass {
    string product;
    float price;
} a, b, c;
a = b + c;

HEre, it is not obvious that the result of the addition operation on b and c dose. In fact, this code alone would cause a compilation error, since the type myclass has no defined behavior for additions.However, C++ allows most operators to be overloaded so that their behavior can be defined for just about any type, including classes. Here is a list of all the operators that can be overloaded:

Overloadable Operators
+ - * / = < > += -= *= /= << >> <<= >>= == != <= >= ++ – % & ^ !

Operators are overloaded by means of operator functions , which are regular functions with special names: their name begins by the operator keyword followed by the operator sign that is overloaded. THe syntax is :

type operator sign(parameters) {/*...body...*/}

For example, cartesian vectors are sets of two coordinates: x and y. The addition operation of two cartesian vector is defined as the addition both x coordinates together, and both y coordinates together. For example, adding the cartesian vectors (3, 1) and (1, 2) together would result in (3+1, 2+1) = (4,3). This could be implemented in C++ with the following code:

// overloading operators example
#include <iostream>
using namespace std;

class CVector {
  public:
    int x,y;
    CVector () {};
    CVector (int a, int b) : x(a), b(y) {}
    CVector operator + (const CVector&);
};
CVector CVector::operator+ (const CVector& param) {
    CVector temp;
    temp.x = x + param.x;
    temp.y = y + param.y;
    return temp;
}

int main () {
    CVector foo (3,1);
    CVector bar (1,2);
    CVector result;
    result = foo + bar;
    cout << result.x << ',' << result.y <<'\n';
    return 0;
}

If confused about so many appearances of CVector, consider that some of them refer to the class name (i.e., the type) CVector and some others are functions with that name (i.e., constructors, which must have the same name as the class). For example:

CVector (int, int) : x(a), y(b) {}   // function name CVector (constructor)
CVector operator + (const CVector&); // function that returns a CVector

THe function operator+ of class CVector overloads the addition operator (+) for that type. Once declared, this function can be called either implicitly using the operator, or explicitly using its functional name:

c = a + b;
c = a.operator + (b);
  • THe keyword this

The keyword this represents a pointer to the object whose member function is being executed. It is used within a class’s member function to refer to the object itself.

One of its uses can be to check if a parameter passed to a member function is the object itself. For example:

// example on this
#include <iostream>
using namespace std;

class Dummy {
  public:
    bool isitme (Dummy& param);
};

bool Dummy::isitme (DUmmy& param)
{
    if (&param == this) return true;
    else return false;
}

int main () {
    Dummy a;
    Dummy* b = &a;
    if ( b->isitme(a))
        cout << "yes, &a is b\n";
    return 0;
}

It is also frequently used in operator= member functions that return objects by reference.

  • Static members

A class can contain static members, either data or functions.

A static data member of a class is also known as a “class variable, because there is only one common variable for all the objects of that same class, sharing the same value; i.t., its value is not different from one object of this class to another.

class Dummy {
  public:
    static int n;
    DUmmy () {n++};
};
...

In fact, static members have the same properties as non-member variables but they enjoy class scope. For that reason, and to avoid them to be declared several times, they cannot be initialized directly in the class, but need to be initialized somewhere outside it.

Classes can also have static member functions. THese represent the same: members of a class that are common to all object of that class, acting exactly as non-member functions but besing accessed like members of the class. Because they are like non-member functions, they cannot access non-static members of the class (neither member variables nor member functions). They neither can use the keyword this.

  • Const member functions

WHen an object of a class is qualified as a const object:

const MyClass myobject;

THe access to its data members from outside the class is restricted to read-only, as if all its data members were const for those accessing them from outside the class. Note though, that the constructor is still called and is allowd to initialize and modify these data members.

The member functions of a const object can only be called if they are themselves specified as const members.

const objects are limited to access only member functions marked as const, but non-const objects are not restricted and thus can access both const and non-const member functions alike.

  • Class templates

Just like we can create function templates, we can also create class templates, allowing classes to have members that use template parameters as types.

template <class T>
class mypair {
    T value [2];
  public:
    mypair (T first, T second)
    {
        values[0] = first; value[1] = second;
    }
}

The class that we have just defined serves to store two elements of any valid type.

  • Template specialization

It is possible to define a different implementation for a template when a specific type is passed as templated argument. This is called a template specialization.

template <class T> class mycontainer {...};
template <> class mycontainer <char> {...};

The first line is the generic template, and the second one is the specialization.

When we declare specializations for a template class, we must also define all its members, even those identical to the generic template class, because there is no “inheritance” of members from the generic template to the specialization.

  • Special members

    Special member functions are member functions that are implicitly defined as member of classes under certain circumstances. There are six:

    Member functionTypical form for class C
    Default constructorC::C();
    DestructorC::~C()
    Copy constructorC::C (const C&)
    Copy assignmentC& operator=(const C&)
    Move constructorC::C (C&&)
    Move assignmentC& operator=(C&&);
  • Friendship and inheritance

  • Friend functions

In principle, private and protected members of a class cannot be accessed from outside the same class in which they are declared. However, this rule does not apply to “friends”.

Friends are functions or classes declared with the friend keyword.

A non-member function can access the private and protected members of a class if it is declared a friend of that class. That is done by including a declaration of this external function within the class, and preceding it with the keyword friend.

class Rectangle {
    friend Rectangle duplicate (const Rectangle&);
}

  • Friend classes

Similar to friend functions, a friend class is a class whose members have access to the private or protected members of another class.

class Rectangle {
   ...  
}
class Square {
    friend class Rectangle;
    ...
}

  • Inheritance between classes

Classes in C++ can be extended, creating new classes which retain characteristics of the base class. This process, known as inheritance, involves a base class and a derived class: The derived class inherits the members of the base class, on top of which it can add its own members.

  • What is inherited from the base class?

In principle, a publicly derived class inherits access to every member of a base class except:

	1. its constructors and its destuctor


 		2. its assignment operator members (operator=)
           		3. its friends
                     		4. its private members
  • Multiple inheritance

A class may inherit from more than one class by simply specify more base classes, separated by commas, in the list of a class’s base classes (i.e., after the colon). For example, if the program had a specific class to print on screen called Output, and we wanted our classes Rectangle and Triangle to also inherit its members in addition to those of Polygon we could write:

class Rectangle: public Polygon, public Output;
class Triangle: public Polygon, public Output;

  • Polymorphism

Before getting any deeper into this chapter, you should have a proper understanding of pointers and class inheritance.

  • Pointers to base class

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature.

  • Virtual members

A virtual member is a member function that can be redefined in a derived class, while preserving its calling properties through references. The syntax for a function to become virtual is to precede its declaration with the virtual keyword.

  • Abstract base classes

Abstract base classes are something very similar to the Polygon class . They are classes that can only be used as base classes, and thus are allowed to have virtual member functions without definition (known as pure virtual functions). The syntax is to replace their definition by =0 (an euqal sign and a zero).

<think>我们面对的用户意图是:用户不清楚"利用空闲符号做运算"及"试试|"具体所指的运算和需求。用户的问题只有两个短语:"试试|"和"用空闲符号做运算"。 经过分析,用户可能是在探索C++中如何自定义运算符,特别是使用一些不常用或者重载后不会引起混淆的符号(如`|`)来实现特定的运算。由于之前对话历史中提到过重载运算符(如^、%、~等),用户可能想进一步尝试使用`|`符号。 因此,我们需要搜索关于在C++中重载运算符`|`的相关信息,以及如何利用它来实现特定的运算(例如向量点积、集合运算、或其他自定义运算)。同时,我们还需要考虑如何安全地重载运算符,避免常见的陷阱。 搜索词: 1. "C++ overload operator |" 2. "C++ custom operator examples" 3. "best practices for operator overloading in C++" 根据搜索,我们可能得到以下信息: 1. 在C++中,运算符`|`原本是按位或运算符,但可以被重载。 2. 重载运算符`|`的常见用途包括: - 集合的并集(例如,自定义集合类) - 管道操作(类似于Unix shell中的管道,用于函数式编程) - 向量点积(但注意,按位或通常不用于数学点积,点积更常用`*`或重载`operator*`,但也可以自定义) 3. 重载运算符时需要注意运算符的优先级和结合性,因为重载不会改变这些固有属性。 因此,我们可以为用户提供以下内容: - 重载运算符`|`的基本语法。 - 使用`|`运算符实现几种常见运算的示例(如集合并集、管道操作、向量点积等)。 - 注意事项(例如,运算符重载的最佳实践,何时适合重载,何时不适合)。 下面开始组织回答: 首先,介绍重载运算符`|`的基本语法。然后,给出几个示例,每个示例展示一种用途。最后,给出一些注意事项。 注意:代码严格使用三个反引号,并注明语言类型。公式使用$或$$包裹。 由于用户的问题比较模糊,我们尽可能提供多种可能的用法,让用户可以根据自己的需求选择。 以下是回答内容: </think>### C++运算符重载与空闲符号`|`的实用指南 #### **1. 运算符`|`的重载基础** 在C++中,`|`默认为**按位或运算符**,但可通过重载实现自定义运算: ```cpp class Vector { public: double x, y; // 重载|为向量点乘 double operator|(const Vector& other) const { return x * other.x + y * other.y; } }; Vector a{1.0, 2.0}, b{3.0, 4.0}; double dot = a | b; // 结果:$1 \times 3 + 2 \times 4 = 11$ ``` #### **2. 空闲符号`|`的扩展应用** **(1) 集合运算(并集/交集)** ```cpp class IntSet { std::set<int> data; public: // 重载|为集合并集 IntSet operator|(const IntSet& other) const { IntSet result; std::set_union(data.begin(), data.end(), other.data.begin(), other.data.end(), std::inserter(result.data, result.data.begin())); return result; } }; ``` **(2) 管道式函数组合** ```cpp // 定义函数包装器 template<typename Func> auto operator|(Func f, Func g) { return [=](auto x) { return g(f(x)); }; } // 使用示例 auto increment = [](int n) { return n + 1; }; double square = [](int n) { return n * n; }; int result = (increment | square)(3); // $(3+1)^2 = 16$ ``` #### **3. 重载限制与最佳实践** - **优先级约束**:运算符`|`优先级较低(低于`+`/`-`),需注意表达式逻辑 ```cpp // 可能导致歧义:需显式括号 double res = (a | b) + c; ``` - **类型安全**:使用SFINAE或C++20约束类型 ```cpp template<typename T> auto operator|(const T& a, const T& b) -> std::enable_if_t<std::is_class_v<T>, double> { ... } ``` #### **4. 替代符号对比** | 符号 | 默认用途 | 自定义适用场景 | |------|-----------|--------------------| | `\|` | 按位或 | 集合操作/函数组合 | | `^` | 按位异或 | 向量叉积/指数运算 | | `~` | 按位取反 | 近似相等判断 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值