Adrian Munteanu
Adrian Munteanu

Reputation: 124

C++ order of operations accessing class member

Can the line in main work? Maybe other operators? Some suggestions? I think the order of operations is the problem here. Is it a must to use b.addA("P"); b.R("P").ref(b.R("P")); ?

I want to add references from an object to others and make relations between objects, like a database model.

#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;
}

Upvotes: 0

Views: 178

Answers (2)

grv
grv

Reputation: 1153

To begin with the line in main will surely work. Now how that happens is a question you would be interested in? When you call the addA("P") it creates the object of class A and returns it by reference, now this object of A calls its member fn ref(A&), as you can see you need to pass an object of A by reference to this function which are doing by calling b.R("P") which in itself returns reference to just now added object with string "P". Now you have

A'.ref(A")

where A' A" are referenced object returned by two different fn of B class(bydway in this case A'A" will be the same).

The above call will return another object of class A by reference which you can assign to any other instance of A like

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

You are just doing chained function call and by returning object by references you make sure that nothing is going on in temporary variables which you might lose. Hope I have answered your question.

Upvotes: 0

David Hammen
David Hammen

Reputation: 33116

Can the line in main work?

Sure. There are only two operators in play here, function call and reference (the dot operator). You would have a problem if association was right to left or if function call had precedence over reference. That isn't the case. Function call and reference have the same precedence and the association is left to right. That's just what you want.

There is a problem with your code, however. It's the member function B::A. Within the context of class B, this changes the meaning of A from class A to member function B::A(std::string). Your code fails to compile on multiple compilers for me, but it does compile with clang 3.1. That looks like a clang bug to me. (Addendum: That this does compile with clang is OK because the rule that is being violated is one of those nasty "no diagnostic is required" rules.) Your code is illegal; it (ideally) should fail to compile.

A better name for that function is findA. This name doesn't collide with the class name and it makes the code self documenting.

Aside: You might want to think of having that function return a pointer rather than a reference. Exceptions should be used for exceptional events (i.e., errors). Is the fact that (for example) "Foo" is not represented in your vector truly worthy of throwing an exception?

Upvotes: 2

Related Questions