【问题标题】:Overriding [] c++覆盖 [] c++
【发布时间】:2017-04-24 22:28:08
【问题描述】:

我目前正在编写自己的 String 类。 这是标题

#pragma once

class String
{
private:
    char* m_Beginning;
    int m_Length;

public:
    // Constructors
    String();
    String(const String&);
    String(const char*);

    // Destructor
    ~String();

    // Operations
    String& operator=(const String&);
    String operator+(const String&)const;
    String& operator+=(const String&);
    char operator[](int _Index)const;

    // Methods
    void Append(const String&);
    String Concatenate(const String&)const;
    int Length()const { return m_Length; };
    void Clear();
};

这是类描述

#include "String.h"
#include <cstring>
#include <iostream>

String::String()
{
    m_Beginning = nullptr;
    m_Length = 0;
}

String::String(const String& _String)
{
    m_Length = _String.Length();
    m_Beginning = new char[m_Length];
    for (int i = 0; i < m_Length; ++i)
    {
        m_Beginning[i] = _String[i];
    }
}

String::String(const char* _String)
{
    m_Length = strlen(_String);
    m_Beginning = new char[m_Length];
    for (int i = 0; i < m_Length; ++i)
    {
        m_Beginning[i] = _String[i];
    }
}

String::~String()
{
    delete[] m_Beginning;
}

String& String::operator=(const String& _String)
{
    Clear();
    m_Length = _String.Length();
    m_Beginning = new char[m_Length];
    for (int i = 0; i < m_Length; ++i)
    {
        m_Beginning[i] = _String[i];
    }
    return *this;
}

String String::operator+(const String& _String)const
{
    String NewString(*this);
    NewString += _String;
    return NewString;
}

String& String::operator+=(const String& _String)
{
    for (int i = 0; i < _String.Length(); ++i)
    {
        m_Beginning[m_Length + i] = _String[i];
    }
    m_Length += _String.Length();
    return *this;
}

char String::operator[](int _Index)const
{
    return m_Beginning[_Index];
}


void String::Append(const String& _String)
{
    *this += _String;
}

String String::Concatenate(const String& _String) const
{
    return (*this + _String);
}

void String::Clear()
{
    delete[] m_Beginning;
    m_Beginning = nullptr;
    m_Length = 0;
}

我想问的是如何覆盖运算符 [] 以便我为某个单元格设置一个值,而不仅仅是提取它。

str("ABCD");
str[2] = 'Z'; // and str will become "ABZD".

谢谢你:)

【问题讨论】:

  • 旁注:如果您正在编写自己的带有运算符重载的类,我强烈建议您阅读Operator overloading 以使这些东西在惯用语上是正确的(并避免不断重复自己)。同样,对于资源管理类,您需要阅读 What is the copy-and-swap idiom? 以了解构造函数和赋值操作的相同正确性/简化。
  • 所有以下划线开头并以多个下划线或大写字母开头的名称都保留用于任何范围的实现。您的程序格式不正确。
  • 感谢您提供的信息。我会记住的:)
  • 提示:您可以在en.cppreference.com/w/cpp/string/basic_string 查看 STL std::basic_string 的声明,以重用原型并编写自己的实现。

标签: c++ operator-overloading operator-keyword


【解决方案1】:

您需要返回对字符串内部缓冲区中字符的引用。您还需要为您的字符串提供 const 和非 const 版本的 operator[]。

在您的字符串标题中:

const char& String::operator[](int _Index) const;
char& String::operator[](int _Index);

在您的 .cpp 文件中:

const char& String::operator[](int _Index) const
{
    return m_Beginning[_Index];
}

char& String::operator[](int _Index)
{
    return m_Beginning[_Index];
}

当您尝试使用如下代码在字符串中分配一个字符时:

str[2] = 'Z'; // and str will become "ABZD".

编译器将有效地生成与此代码相同的代码:

{
  char& ch = str.m_Beginning[2];
  ch = 'Z';
}

此外,对于字符串情况,最好将这些方法内联在头文件中。还有一点,通常最好在此处放置一个断言来验证索引是否超出范围并且已分配 m_Beginning:

const char& operator[](int _Index) const
{
    assert(m_Beginning && _Index>=0 && _Index<m_Length);
    return m_Beginning[_Index];
}

char& operator[](int _Index)
{
    assert(m_Beginning && _Index>=0 && _Index<m_Length);
    return m_Beginning[_Index];
}

【讨论】:

  • 感谢它的工作!你能解释一下它为什么起作用吗?我将不胜感激。
  • 无论如何,单行返回很可能会被编译器内联。 IMO,尤其是在开始时,请将您的代码放在 cpp 文件中。
  • @Donnie 不,如果它在 .cpp 中,编译器不会内联任何内容。只有链接器可以做到这一点。 MS 编译器将仅在启用 LTCG(链接时间代码生成)的情况下内联此编译器。
  • @Pavel:好吧,如果链接时间优化正在发挥作用,它可以在链接阶段内联,但您需要确保您实际使用开关来启用 LTO。跨度>
  • @pavel - 既然你不相信我,我会提供一个较早的讨论:stackoverflow.com/questions/1443982/…
猜你喜欢
  • 2011-06-11
  • 2017-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 2012-12-17
  • 2017-02-25
相关资源
最近更新 更多