【问题标题】:C++ order of operations accessing class member访问类成员的 C++ 操作顺序
【发布时间】:2012-09-22 11:53:40
【问题描述】:

主线可以工作吗?也许其他运营商?一些建议? 我认为操作顺序是这里的问题。是否必须使用 b.addA("P"); b.R("P").ref(b.R("P")); ?

我想将一个对象的引用添加到其他对象并在对象之间建立关系,例如数据库模型。

#include <iostream>
#include <vector>
#include <string>

class A;
class B;

class A{
    std::string _name;
    std::vector<A*> _refs;
public:
    A(std::string="");
    A& ref(A&);
    std::string name() const;
};

class B{
    std::string _name;
    std::vector<A> _as;
public:
    B(std::string="");
    A& addA(std::string);
    A& R(std::string);
};

A::A(std::string nm){
    _name=nm;
}

A& A::ref(A &a){
    for(int i=0; i<_refs.size(); i++)
        if(_refs[i]==&a)
            return a;
    _refs.push_back(&a);
    return a;
}

std::string A::name() const{
    return _name;
}

B::B(std::string nm){
    _name=nm;
}

A& B::addA(std::string nm){
    for(int i=0; i<_as.size(); i++)
        if(_as[i].name()==nm)
            return _as[i];
    _as.push_back(A(nm));
    return _as[_as.size()-1];
}

A& B::R(std::string nm){
    for(int i=0; i<_as.size(); i++)
        if(_as[i].name()==nm)
            return _as[i];
    throw std::string("invaild A");
}

int main(){
    B b;
    b.addA("P").ref(b.R("P"));
    return 0;
}

【问题讨论】:

  • (除其他外)我认为这是错误的:_as.push_back(A::A(nm));。也许你的意思是_as.push_back(A(nm));
  • @MihaiTodor:我认为这没关系,因为我想存储在我的 A 类型向量中,命名为 _as 我的“子对象”
  • 你不能/不应该直接调用类的构造函数,即使 VS2010 似乎允许它。更正后,我仍然在 GCC 中收到一个奇怪的错误,但我不知道为什么。
  • @MihaiTodor:我会打电话给 A(nm);为了创建 A 类型的对象,但它需要 B::A(std::string)
  • 所以,是的,原来是it's illegal to have a class method sharing the same name as a class in the same context。你是这个限制的受害者。 GCC 足够聪明,可以禁止你这样做。

标签: c++ class pointers operator-keyword


【解决方案1】:

main中的线可以工作吗?

当然。这里只有两个运算符,函数调用和引用(点运算符)。如果关联是从右到左的,或者函数调用优先于引用,则会出现问题。事实并非如此。函数调用和引用具有相同的优先级,并且关联是从左到右的。这正是你想要的。

但是,您的代码有问题。它是成员函数B::A。在类B 的上下文中,这将A 的含义从class A 更改为成员函数B::A(std::string)。您的代码无法在多个编译器上为我编译,但它确实使用 clang 3.1 编译。 这对我来说似乎是一个 clang 错误。附录:这确实可以用 clang 编译,因为被违反的规则是那些讨厌的“没有诊断是required”规则。)您的代码是非法的;它(理想情况下)应该无法编译。

该函数的更好名称是findA。此名称不会与类名冲突,它会使代码自我记录。

旁白:您可能想考虑让该函数返回指针而不是引用。异常应该用于异常事件(即错误)。 (例如)“Foo”未在您的向量中表示的事实真的值得抛出异常吗?

【讨论】:

  • 把 A& B::A(std::string) 改为 A& B::R(std::string),问题依旧…… :(
  • 在VS2010上也可以编译,但还是illegal
  • 我想返回引用以便编写一个链式指令,就像缅因州的那个。
  • @Adrian Dude,b.addA("P").ref(b.R("P")); 行将首先评估b.R("P")。我不确定你想在这里实现什么,但如果你想在b.addA 之后执行b.R("P"),那么这不是这样做的方法。
  • @MihaiTodor:我也注意到了,但如果可能的话,我想做类似的事情。例如,如果我可以使用其他运算符从左到右进行评估,就像它所写的那样......
【解决方案2】:

从 main 中的行开始肯定会起作用。 现在这是如何发生的,是您感兴趣的问题吗? 当您调用 addA("P") 它创建类 A 的对象并通过引用返回它, 现在 A 的这个对象调用它的成员 fn ref(A&),如您所见,您需要通过引用此函数来传递 A 的对象,该函数通过调用 b.R("P") 本身返回刚才的引用添加带有字符串“P”的对象。现在你有

A'.ref(A")

其中 A' A" 是由 B 类的两个不同 fn 返回的引用对象(顺便说一下,在这种情况下 A'A" 将是相同的)。

上述调用将通过引用返回另一个 A 类对象,您可以将其分配给 A 的任何其他实例,例如

A t; t = b.addA("P").ref(b.R("P"));

您只是在进行链式函数调用,并通过引用返回对象来确保您可能丢失的临时变量中没有发生任何事情。 希望我已经回答了你的问题。

【讨论】:

  • 问题是首先调用了 b.R("P")。如果我在类之间创建友谊并使 ref(std::string) 通过指向 b 的指针进行搜索,它就会得到想要的结果。更详细地说,在 A 中我可以有 B* _myb 并调用 ref(std::string nm) _myb->R(nm) 来找到 A 类型的对象并将其添加到 refs,然后调用 ref 就像b.addA("P").ref("P")。这行得通。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-08
  • 2011-11-03
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多