【问题标题】:CString a = "Hello " + "World!"; Is it possible?CString a = "你好" + "世界!";可能吗?
【发布时间】:2011-02-20 03:50:36
【问题描述】:

我正在创建自己的字符串 class,并且我想确保 CString a = "Hello " + "World!"; 有效(即不会给出编译器错误,例如:cannot add 2 pointers)。

我的字符串class 会在需要时自动转换为char*,因此编写printf(a) 不会破坏代码。

有没有办法替换 characters 周围的编译器行为? (即在逗号之间,"abc")。或者,改变+ 操作符的行为来处理字符串

【问题讨论】:

  • 编写一个好的字符串类真的很难。 std::string 真的非常好。例如,隐式转换为 char* 在编写 printf(str); 时看起来是个好主意,但在编写 printf("%s\n", str); 时却是个糟糕的主意除非你非常小心,否则这是行不通的。 MFC 的 CString 设法像这样工作,而且它必须经历的可怕的脏跳转不值得费心(如果你删除 (char*)str 会严重失败)。除非您有充分的理由不(家庭作业?),否则我建议您不要编写自己的字符串类并使用 std::string
  • 编写自己的字符串类的一个重要原因是学习......当然,在生产代码中,这是一个错误。
  • 有更好的学习方法。弦乐类设计充满了巨大但微妙的陷阱,这些陷阱一次又一次地被绊倒——如果你的导师没有指出这些,你所做的就是记住它们并将它们应用到任何地方。
  • 每个人都告诉我我所做的是一个错误,但每次我证明是错误的(迟早)。我只是不喜欢使用 std::string 并且喜欢使用更简单的东西。我整天都在这门课上工作,结果非常好。另一件事是,我真的想要一些不在 std::string 中的其他方法,因此派生它相当复杂(据我所知,它可能是一个不可派生的类),并且在方法时我会避免编写全局函数应该是方法。这只是为了内部开发,所以我认为这不是一个错误。
  • 相信我——我以前写过我自己的字符串类,不止一次,而且不值得。该语言提供了一种优秀的语言,已经由对图书馆开发有很多了解的聪明人实施。如果您打算维护代码,编写自己的字符串类是浪费您的时间,您可能会花在功能上。如果有一些你不能用 std::string 做的事情,请考虑在这里提出一个问题——这可能是可能的,但你还没有看到怎么做。此外,非成员函数(全局使其听起来很糟糕)在 C++ 中占有一席之地。

标签: c++ string pointers operator-overloading


【解决方案1】:

你不能完全那样做,因为你只能为类类型重载运算符,而字符串文字没有类类型。

您可以利用在预处理期间发生的字符串文字连接:

CString a = "Hello " "World!";

或者您可以创建一个 CString 临时并附加到它:

CString a = CString("Hello ") + "World!";

或者你可以有一个CString 构造函数,它接受多个参数:

CString a("Hello ", "World!");

【讨论】:

  • 但是你已经可以使用 std::string str(std::string("Hello") + "World");!!!!
  • @大卫:是的;和...?我不确定我明白你在说什么。
  • OP 在任何情况下都不可能改进 std::string ,所以整个练习只是为了学习。将他的课程与 std::string 进行比较是没有意义的。
  • 我已经可以做 CString a = CString("Hello")+" World";但我只是想让它更简单。这不是必需品,更像是个人品味。我确实知道这很难做到/不可能,但我只是想澄清一下。
【解决方案2】:

正确答案

没有。 您不能为内置函数重载运算符,例如指针。

James McNellis 已经回答了这个问题,所以我不会详细说明。

可能的替代方案...

(我使用 std::string 是因为我没有关于您的内部字符串的信息)

使用 typedef 会给你的语法添加一些糖:

typedef std::string S_ ;

int main(int argc, char* argv[])
{
   std::string s = S_("Hello") + S_(" World") ;

   std::cout << "s : " << s << std::endl ;

   return 0 ;
}

但是,我不会为了一点糖就用两个字符的符号污染全局命名空间......据我所知,代码效率低下(创建了两个字符串对象,加上一个临时对象,没有保证编译器会优化它...)

为了好奇……

出于好奇,通过将字符串包装成一个瘦类,您可以“添加”这两个指针。

首先,让我们创建包装器:

class StringThinWrapper
{
   public :

      StringThinWrapper(const char * p) : m_p(p) {}
      operator const char * () const { return m_p ; }

   private :
      const char * const m_p ;
} ;

正如你所看到的,它是内联的,并且什么都不做......不过,它能够将自己转换为一个 const char * 指针(这种 hack 很危险,所以请确保这是你想要做的) .

然后,对于这个包装器,让我们重载加法运算符:

inline std::string operator + (const StringThinWrapper & lhs, const StringThinWrapper & rhs)
{
   std::string s(lhs) ;
   s += rhs ;
   return s ;
}

现在,让我们使用包装器编写一个main 函数,为易于使用而进行类型定义:

typedef StringThinWrapper S_ ;

int main(int argc, char* argv[])
{
   std::string s = S_("Hello") + S_(" World") ;

   std::cout << "s : " << s << std::endl ;

   return 0 ;
}

编译并给出以下结果:

s : 你好世界

免责声明:我只是想尝试一下您的问题给我的想法,并与您分享。不要仅仅因为可以应用这种代码。事实上,这段代码应该在使用之前进行改进以有效地覆盖所有情况,即使这样,一个简单的typedef std::string S_ ; 恕我直言会更好。

AFAIK,我不会使用它,因为我对当前的 STL API 很满意。

那么 C++0x 呢?

在 C++0x 中,您将能够创建自己的文字。代码有点像:

std::string operator "str"(const char * p)
{ 
    return std::string(p); 
}

你会这样使用它:

int main(int argc, char * argv[])
{
   std::string s = "Hello"str + " World"str ;

   std::cout << "s : " << s << std::endl ;

   return 0 ;
}

有关详细信息,请参阅以下 SO 问题:What new capabilities do user-defined literals add to C++?

【讨论】:

  • 我明白你的意思,但使用 _S("some string") 与编写 CString("some string") 大致相同。我只是在寻找一种完全消除这种情况的方法。我不喜欢 STL,这就是为什么我要制作自己的小课程。我听说过 C++0x,但还没有接触过它。 “字面重载”确实是一种有趣的方法(我希望这在技术上是正确的)。是否有可能替换 "" 文字,从而使我的代码工作?
  • @Sanctus2099 :当然是一样的,但是S_ 表示法短了 5 个字符,因此读起来更悦耳……同样,James McNellis 说得对:一个可以'不要重载内置的运算符,所以 James' 和我的答案都是你想要的行为的最接近的近似值。
  • @sanctus - 不要使用 _S。这是一个保留名称。不,您将无法替换 "" 以使您的代码在 0x 中工作。
猜你喜欢
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
  • 2015-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多