【问题标题】:Constructing objects in c++在 C++ 中构造对象
【发布时间】:2017-02-22 23:31:45
【问题描述】:

所以,我来自 Java,学习 c++。我想实现一个可以这样调用的程序,由一个测试文件(boots)提供:

auto subject = anagram::anagram("diaper");
auto matches = subject.matches({"hello", "world", "zombies","pants"});
vector<string> expected;
BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), matches.begin(), matches.end());

我说对了吗,anagram::anagram(...) 是一个构造函数,构造一个提供方法matches(...) 的对象?因为在我的实现中(参见下文),我收到一条错误消息(不是英语),例如“无法直接调用构造函数”。我认为 C++ 中的构造函数有一些我不理解的地方。

// this is part of my implementation of anagram.h
class anagram{

public:
    anagram(const string a);
    vector<string> matches(vector<string> &list);

private:
    string a;
    bool isAnagram(string s);    
};

我知道的唯一另一件事是anagram::anagram(...) 可能是一个静态方法,其返回值类似于this,但这对我来说没有意义。所以如果有人能解释一下就好了:)

【问题讨论】:

  • auto subject = anagram::anagram("diaper"); 不是有效的构造函数调用。
  • 它可能是命名空间内的工厂函数。
  • 错字;构造函数被“调用”,如ClassName(stuff) 或ClassName{stuff}。您没有资格调用像 `CalssName::ClassName(stuff)
  • 好的,我知道它不是构造函数,但也不是错字(我很确定),因为它是在线代码练习网站提供的测试文件。你能详细说明那个工厂函数吗?
  • @asu 你是对的,我自己会以不同的方式编写该代码,但由于它是一个测试,我需要坚持我所得到的并提供那个无用的命名空间

标签: c++ object constructor static


【解决方案1】:

因为你来自java你习惯看到类似这样的东西:

 someobject T = new someObject(argument);

在 C++ 中,您以不同的方式构造一个类:

 someObject T(argument);

你在 c++ 中创建了一个名为 T 的对象。另一种方法是创建一个指向对象的指针:

someObject *T = new someObject(argument);

这更类似于 java 但现在您必须手动删除该指针。在堆栈而不是堆上创建对象总是更好。它避免了内存泄漏。


回答你的问题:你错了。您像我之前向您展示的那样调用构造函数。您对如何调用静态成员函数是正确的,但这不适用于 Ctor,因为它永远不能是静态的也不能是虚拟的。

【讨论】:

  • 在可以使用堆栈的情况下使用堆可以有时会有好处。我曾经遇到过这样一种情况,我在堆栈上分配了一个大数组,它的性能比std::vector(内部使用堆)差得多;可能是因为缓存的原因。但在一般情况下,我完全同意。
  • 所以它实际上是一个静态函数?但是matches 仍然是 angram 类的对象,对吧?
  • 是的,但是值得指定matches 的类型会使代码更清晰,而不是更长。当您有长名称时(例如处理迭代器、元组等)时,它很有用。
  • @suffi 不,它不是静态函数!!!!!! Tor 不能是静态的!!!!
  • 呃,我不会将构造函数称为静态函数,因为这很模糊。执行someObject(argument) 将有效地分配和构造someObject 对象。您可能对object lifetimes 也感兴趣
【解决方案2】:

如果调用anagram::anagram 必须工作anagram 是其中的命名空间,则定义一个名为anagram 的函数以返回一个对象,您可以在该对象上调用matches 方法:

namespace anagram {
  SomeType anagram(string n) { return SomeType(n); }
};

这也可以是命名空间 anagram 内的类名 anagram。

这不可能是静态方法,因为除了 ctor 之外没有任何方法可以使用类的名称作为标识符。

【讨论】:

  • +1 就是这样,但我觉得@revolver_ocelot 快一点,虽然我一开始没听懂他在说什么,谢谢! :)
【解决方案3】:

它可以使用您显示的语法的一种方法是,如果将类 anagram 放置在类似命名的命名空间中:

#include <string>
namespace anagram 
{
class anagram
{
  public:
    anagram(std::string s) {}
};
}

int main() 
{
    auto subject = anagram::anagram("diaper");
}

http://ideone.com/1OVhIz

【讨论】:

  • 这无关紧要,因为他假设anagram的构造函数可以像任何其他静态方法一样被调用。
  • 这样做有意义吗?
  • 它只是为您提供与您提到的相同的语法,但它是无用的冗长,imo。如果没有命名空间,你最终只会做anagram("thing") 而不是anagram::anagram("thing")...我认为这不是更好。编辑:特别是考虑到auto thing = anagram::anagram("foo"); 甚至比anagram::anagram thing{"foo"}; 更长
  • @suffi 好吧,将您的类/函数放在全局命名空间之外以避免名称与不这样做的人的代码冲突确实是有意义的。而且,如果您的项目涉及字谜,那么拥有一个具有类anagram、辅助函数is_anagram 以及与字谜处理艺术相关的其他内容的命名空间可能是合乎逻辑的。在考虑如何调用这样的命名空间时,首先想到的是名称 anagram。所以顺便说一下,这样的命名可能是有道理的。将每个类放在具有相同名称的唯一命名空间中肯定是没有意义的。
【解决方案4】:

语法实际上看起来与 Java 中的相似(当然,new 除外):

auto subject = Anagram("diaper");

但是有一个更简单的方法:

Anagram subject("diaper");
Anagram subject{"diaper"}; // C++11 and newer

还要注意,如果Anagram 有一个默认构造函数,它会在你定义它时被构造——它不能是null 或类似java 的东西,除非你使用* 指针。

Anagram subject;

您也可以构建一个临时的Anagram 对象,这样您就不需要定义subject 变量:

auto matches = Anagram{"diaper"}.matches({"hello", "world", "zombies","pants"});

如果你想使用动态分配,你可以使用new,但是当你不再需要时,没有任何GC来删除该值......!

Anagram* subject = new Anagram("diaper");
// ... do some stuff with subject...
delete subject; // Destroy the dynamically allocated subject and deallocate it

如果您想使用动态内存分配,我建议您使用智能指针,您可以在 cpprefrence page 上找到它。与手动分配内存相比,它们具有许多优势。

【讨论】:

    猜你喜欢
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多