Any way to overload [ ] for vector of structure?

In summary, the author attempted to overload [] on vector of structure, but failed. They provide a working example of a class that overloads [] and provides a more detailed explanation of what is going wrong.
  • #1
yungman
5,718
241
I have been studying overloading [ ]. I understand how it works from the book. I experiment using vector of structure and obviously I can't make it work. I wonder if it is possible to overload [] on vector of structure. Here is what I have and it's not even close to working, what can I do to make this work?

C++:
#include <iostream>
#include <vector>
using namespace std;
class VecA 
{
private:
    struct Directory { char name[25]; int amount; };
    vector<Directory>Ivar(3); 
public:    
    VecA(int sub1, int sub2, int sub3) //constructor with 3 parameters of int
          {Ivar[0].amount = sub1; Ivar[1].amount = sub2; Ivar[2].amount = sub3;}
        int &operator[](int position){  return Ivar[position].amount;}
};
int main()
{    VecA anil(1, 2, 3);
    cout << anil[0] << ", " <<anil[1] << ", " << anil[2] << "\n\n";
    return 0;
}

In the code, I try to return Ivar[position].amount, it flagged me. In fact, it flagged me to put vector<Directory>Ivar(3) inside the class definition.

Is it possible to make this work?

Thanks
 
Last edited:
Technology news on Phys.org
  • #2
What have you written as return type of your operator[] overload, and what are you actually returning? Hint: what you return have to match, or at least be implicit castable to the return type.

(The rest of your code also have some issues, but I understand if you want to focus on one issue at a time :wink:)
 
  • #3
Filip Larsen said:
What have you written as return type of your operator[] overload, and what are you actually returning? Hint: they have to match.
I am trying to return an integer. How can I specify it's integer? I have to specify it's the structure Directory first in the statement.

Thanks
 
  • #4
With the declaration "Directory operator[](int position)" what return type do this method has? If you want to return an int then what should you write instead? (This is a very basic method and return type thing, nothing fancy).
 
  • #5
Filip Larsen said:
With the declaration "Directory operator[](int position)" what return type do this method has? If you want to return an int then what should you write instead? (This is a very basic method and return type thing, nothing fancy).
Thanks for the reply, I changed to int operator[](int position){return Ivar[position].amount}. still doesn't work.

Thanks
 
  • #6
yungman said:
I changed to int operator[](int position){return Ivar[position].amount}. still doesn't work.

What doesn't work?

Perhaps you can find inspiration in the following working example:
C++:
//C++ 17
#include <iostream>
#include <vector>

using namespace std;

class DirectoryVector {
    struct Directory {
        string name;
        int amount;
    };
    vector<Directory> entries;
    
public:
    DirectoryVector(const vector<int>& initialAmounts) {
        entries.reserve(initialAmounts.size());
        for (auto &amount : initialAmounts) {
            entries.push_back({"", amount});
        }
    }

    int operator[](int index) const {
        return entries.at(index).amount;
    }
};

int main()
{
    DirectoryVector dv({ 1, 2, 3});
    cout << "dv[2] = " << dv[2];

    return 0;
}
 
  • Like
Likes yungman
  • #7
Your original code for the operator,
C++:
int& operator[] (int position) { return Ivar[position].amount; }
works fine for me, after fixing your other error.

Your real problem is in trying to declare vector<Directory> Ivar(3); as a member of class VecA.

(Aside: When you have several compiler errors, it's always a good idea to tackle the first one first. Errors early in the code can trigger apparent errors in later code that's actually OK.)

I totally understand why you tried to do it this way. When you declare an array of three Directory's and a vector of three Directory's in the body of a function, you do this:
C++:
Directory ArrA[3];
vector<Directory> VecA(3);
It's natural to assume that because you declare an array same way in a class definition, you can do likewise with the vector. Unfortunately, that doesn't work, because the "declaration" of the vector above isn't a pure declaration. The "(3)" invokes a specific non-default constructor of class vector. In the context of a class definition, you have to do that in a constructor for that class.

Filip showed you one way. I'll show you a couple of other ways that might be easier to follow, but might have disadvantages in efficiency or whatever, compared to his method.

Both methods (and Filip's) declare the vector as simply vector<Directory> Ivar; i.e. as an "empty" vector with zero length to start with. Now let's focus on your constructor for VecA, which has to fix the size of the vector.

Method 1: resize the vector in the body of the VecA constructor:

Add the statement Ivar.resize(3); at the beginning of the constructor. I think you can do this yourself. This method uses the default vector constructor to create an empty vector, when the VecA constructor starts up; then resizes the vector to the desired size.

Method 2: Use the VecA constructor's initializer list:

C++:
    VecA(int sub1, int sub2, int sub3) : Ivar(3)
      { Ivar[0].amount = sub1; Ivar[1].amount = sub2; Ivar[2].amount = sub3; }
The initializer at the end of the first line invokes the appropriate vector constuctor on Ivar directly, before any of the code in the body of the VecA constructor is executed. This is a bit more efficient than the first method, because it sets up the vector in one step (construction) instead of two (construction and resizing).
 
Last edited:
  • Like
Likes yungman
  • #8
jtbell said:
The "(3)" invokes a specific non-default constructor of class vector. In the context of a class definition, you have to do that in a constructor for that class.

Edit: In my first comment below I wrote vector<int> member {3}; as an example, but this does not work as intended since 3 is an int and thus seen as an initializer list of one element (the vector size will be 1 afterwards). In my comment I have changed to string so the {3} is parsed as a vector size argument (ref. (3) on https://en.cppreference.com/w/cpp/container/vector/vector). Another good reason to stay away from this vector constructor!

In modern C++ you can actually define a vector (member) variable like vector<string> member {3}; to get it initialized with 3 default-valued string if you really want. But in the present case it sure makes more sense to set the size in a constructor of the class containing the vector, just as you showed in post #9.

Also, yungman may (some day) want to note that there is a difference between a vectors capacity and its size. Setting the size (like resize(3) or via the vector(3) construct) will initialize each member with a default value. I would recommend not to set size directly but instead use push_back to grow the vector as data is needed to ensure the data in the vector makes sense and then, as an allocation optimization that doesn't change the validity of the program, perhaps call reserve first if the number is known in advance.
 
Last edited:
  • Like
Likes yungman
  • #9
jtbell said:
Your original code for the operator,
C++:
int& operator[] (int position) { return Ivar[position].amount; }
works fine for me, after fixing your other error.

Your real problem is in trying to declare vector<Directory> Ivar(3); as a member of class VecA.

(Aside: When you have several compiler errors, it's always a good idea to tackle the first one first. Errors early in the code can trigger apparent errors in later code that's actually OK.)

I totally understand why you tried to do it this way. When you declare an array of three Directory's and a vector of three Directory's in the body of a function, you do this:
C++:
Directory ArrA[3];
vector<Directory> VecA(3);
It's natural to assume that because you declare an array same way in a class definition, you can do likewise with the vector. Unfortunately, that doesn't work, because the "declaration" of the vector above isn't a pure declaration. The "(3)" invokes a specific non-default constructor of class vector. In the context of a class definition, you have to do that in a constructor for that class.

Filip showed you one way. I'll show you a couple of other ways that might be easier to follow, but might have disadvantages in efficiency or whatever, compared to his method.

Both methods (and Filip's) declare the vector as simply vector<Directory> Ivar; i.e. as an "empty" vector with zero length to start with. Now let's focus on your constructor for VecA, which has to fix the size of the vector.

Method 1: resize the vector in the body of the VecA constructor:

Add the statement Ivar.resize(3); at the beginning of the constructor. I think you can do this yourself. This method uses the default vector constructor to create an empty vector, when the VecA constructor starts up; then resizes the vector to the desired size.

Method 2: Use the VecA constructor's initializer list:

C++:
    VecA(int sub1, int sub2, int sub3) : Ivar(3)
      { Ivar[0].amount = sub1; Ivar[1].amount = sub2; Ivar[2].amount = sub3; }
The initializer at the end of the first line invokes the appropriate vector constuctor on Ivar directly, before any of the code in the body of the VecA constructor is executed. This is a bit more efficient than the first method, because it sets up the vector in one step (construction) instead of two (construction and resizing).
That's exactly what happened. I woke up thinking about that, I put the vector declaration out on top of the class declaration and it worked...even before I read your post.

Now I have to spend time going through your post and Filip's post and learn that. I just getting into [] overload, I am still not quite getting use to the idea those overload operators are completely separate from the class and keep putting the class name in front of it regardless what to return.

Thanks
 
  • #10
yungman said:
I am still not quite getting use to the idea those overload operators are completely separate from the class and keep putting the class name in front of it regardless what to return.
No, the overloaded operators are NOT separate from the class they are part of. All of the members of a class are part of the class, which includes data members, function members, and any overloaded operators you throw in.

You should only put the class name at the beginning if the operator is intended to return an object of the class. If the operator is intended to return, say, an int, then the header for the operator would look like this: int operator XX().
An operator could return an object or a reference to an object, as in these examples:
C++:
Vec operator XX()
Vec& operator YY()
 
  • Like
Likes yungman
  • #11
Filip Larsen said:
What doesn't work?

Perhaps you can find inspiration in the following working example:
C++:
//C++ 17
#include <iostream>
#include <vector>

using namespace std;

class DirectoryVector {
    struct Directory {
        string name;
        int amount;
    };
    vector<Directory> entries;
   
public:
    DirectoryVector(const vector<int>& initialAmounts) {
        entries.reserve(initialAmounts.size());
        for (auto &amount : initialAmounts) {
            entries.push_back({"", amount});
        }
    }

    int operator[](int index) const {
        return entries.at(index).amount;
    }
};

int main()
{
    DirectoryVector dv({ 1, 2, 3});
    cout << "dv[2] = " << dv[2];

    return 0;
}
Thanks for you example, problem with me is I have not learn .reserve(0, .at() type of function. I have no idea what they are. I need to go with the more basic way.

thanks
 
  • Sad
Likes pbuk
  • #12
yungman said:
Thanks for you example, problem with me is I have not learn .reserve(0, .at() type of function. I have no idea what they are. I need to go with the more basic way.
These methods of std::vector are fundamental, there is no point using the class if you don't know how to use it. Yet again you have rejected the effort of someone who has invested their time and effort to give you an excellent template to follow and learn from. You will not progress this way.
 
  • Like
Likes Vanadium 50
  • #13
pbuk said:
These methods of std::vector are fundamental, there is no point using the class if you don't know how to use it. Yet again you have rejected the effort of someone who has invested their time and effort to give you an excellent template to follow and learn from. You will not progress this way.
It's easy for you to say, I am stretching already to go beyond the book and the video, there comes a point I have to draw the line and get on with the book. And thanks to other people that take the time to help me here.
 
Last edited by a moderator:
  • Sad
Likes jbriggs444
  • #14
jtbell said:
Your original code for the operator,
C++:
int& operator[] (int position) { return Ivar[position].amount; }
works fine for me, after fixing your other error.

Your real problem is in trying to declare vector<Directory> Ivar(3); as a member of class VecA.

(Aside: When you have several compiler errors, it's always a good idea to tackle the first one first. Errors early in the code can trigger apparent errors in later code that's actually OK.)

I totally understand why you tried to do it this way. When you declare an array of three Directory's and a vector of three Directory's in the body of a function, you do this:
C++:
Directory ArrA[3];
vector<Directory> VecA(3);
It's natural to assume that because you declare an array same way in a class definition, you can do likewise with the vector. Unfortunately, that doesn't work, because the "declaration" of the vector above isn't a pure declaration. The "(3)" invokes a specific non-default constructor of class vector. In the context of a class definition, you have to do that in a constructor for that class.

Filip showed you one way. I'll show you a couple of other ways that might be easier to follow, but might have disadvantages in efficiency or whatever, compared to his method.

Both methods (and Filip's) declare the vector as simply vector<Directory> Ivar; i.e. as an "empty" vector with zero length to start with. Now let's focus on your constructor for VecA, which has to fix the size of the vector.

Method 1: resize the vector in the body of the VecA constructor:

Add the statement Ivar.resize(3); at the beginning of the constructor. I think you can do this yourself. This method uses the default vector constructor to create an empty vector, when the VecA constructor starts up; then resizes the vector to the desired size.

Method 2: Use the VecA constructor's initializer list:

C++:
    VecA(int sub1, int sub2, int sub3) : Ivar(3)
      { Ivar[0].amount = sub1; Ivar[1].amount = sub2; Ivar[2].amount = sub3; }
The initializer at the end of the first line invokes the appropriate vector constuctor on Ivar directly, before any of the code in the body of the VecA constructor is executed. This is a bit more efficient than the first method, because it sets up the vector in one step (construction) instead of two (construction and resizing).

Thanks so much Jtbell. Yes, when I put inside the constructor like in your first example, it works.

Is it because Vector is a class template, not as simple as array? I still have to learn template in the near future. I am pushing way out of the book already. If I follow straightly to the book, I feel I literally learn nothing.

thanks so much for your help.
 
  • #15
I am looking into make the program more interesting, I want to input name and amount and push_back into the vector in the class VecA. Then I want to be able to read it back. Of cause there are issues. I have only one operator[](), if I want to do something like this below, I need to be able to both read and write to the vector. I might be able to use another operator=() to do one job. I just want to get some advice( say hint) which way to go.

This is what I am trying to do, it's not a completer program, just show I want to keep entering name and amount and call to push back into the vector Ivar. Then after I am done, read back the whole list.

C++:
class VecA
{
private: struct Dir { char name[25]; int amount; };//declare a structure
         vector<Dir>Ivar; //declare vector of structure Dir
public:    VecA(char*desc, int amt)  {}
        int &operator[](const int position){  return Ivar[position].amount;}
        void operator=(Dir& rhs) {}//Only one operator=()
};

int main()
{
    char more;
    VecA V;
    struct info { char name[25]; int amount; };
    info person;//declare structure person.
//Input information to person and  push_back into vector Ivar.   
    do
    {
        cin.ignore();
        char name[25];
        int number, amount;
        cin.getline(person.name, 25);
        cin >> person.amount;
        V = person;//using operator=() to copy person into vector to push_back.
        cin.get(more);
    } while (tolower(more) == 'y');
//read back from vector Ivar
    while (!= = false)
        {person = V;//read from Ivar starting from 0.
        //display information
        }
    return 0;
}
I know if I use conventional way, it would be too easy like setName(), getName() etc. I am trying to use overloading operators. Any advice would be helpful.
Thanks
 
Last edited:
  • #16
yungman said:
problem with me is I have not learn .reserve(0, .at() type of function. I have no idea what they are.
Any time you use an STL template class, like vector, or array, or whatever, you should investigate the methods (class functions) and operators that come with the class. A resource I use a lot is cplusplus.com. The VS docs are also helpful.
yungman said:
I might be able to use another operator=() to do one job.
Not the way you show it below. operator=() should not be type void. This operator needs to return something.
yungman said:
void operator=(Dir& rhs) {}//Only one operator=()
operator=() let's you assign one object to another of the same type. If a and b are objects of some type, you can use an overloaded operator=() like this:
C++:
a = b;
which is really like this:
C++:
a.operator=(b);
yungman said:
it would be too easy like setName(), getName() etc. I am trying to use overloading operators. Any advice would be helpful.
That's the way that things are usually done; i.e., with setters and getters. I can't think of a good reason to overload an operator to do either of these tasks.
 
  • Like
Likes pbuk, yungman and Vanadium 50
  • #17
Thanks Mark, I am just thinking out loud, the other voice to me is just let it go and go back to the book! Just finish the chapter and move on. I have times that I spent a lot of time on something, then I found out there is a better way in the later chapters. I think I need to take a night off, I already have a taste using vector here, that's more than the book offers already!
 
  • #18
I am so glad Chapter 14 is coming to an end! Getting ready for the last chapter Inheritance and Polymorphism. Finally the book comes to an end...Last chapter!

My question is how useful in real life are these overload operators? I read from someone that it's more fancy stuffs than really useful in real life programming. Can someone give me a real working example program maybe I can play around like I did with Jtbell's program? If it is useful, I don't think I really learn that deep other than the part in Jtbell's program.

thanks
 
  • #19
yungman said:
how useful in real life are these overload operators?
As a physicist, I would much rather be able to program an equation such as $$\vec r = {\vec r}_0 + {\vec v}_0 t + 0.5 {\vec a} t^2$$ as
C++:
r = r0 + v0 * t + 0.5 * a * t^2
than as something like
C++:
r = vsum (vsum (r0, vsum (vmul (v0, t), 0.5 * a * pow (t, 2))))
 
  • #20
jtbell said:
As a physicist, I would much rather be able to program an equation such as $$\vec r = {\vec r}_0 + {\vec v}_0 t + 0.5 {\vec a} t^2$$ as
C++:
r = r0 + v0 * t + 0.5 * a * t^2
than as something like
C++:
r = vsum (vsum (r0, vsum (vmul (v0, t), 0.5 * a * pow (t, 2))))
But you still need a lot of work to overload this in the program just to make it look better. Not to mention it is definitely extra steps to do the over loading and more chance to make mistakes.

BTW, that's only calculation of magnitude, still need to know the vector part of it. 😊 can you overload that much? Must be very difficult to do this using overloading.

thanks
 
Last edited:
  • #21
yungman said:
My question is how useful in real life are these overload operators?

Some types of operator overloads are very common. I guess you already familiar with general assignment operator, operator= and the std::vector::operator[], but in the standard library you will also find a lot of use of operator(), often used for functors, and operator<< and operator>> for input/output via the iostream library. Another example could be std::string which defines operator+ and operator[] in addition to several others.

As jtbell writes, its also quite common for math libraries (e.g. eigen) to overload the arithmetic operators when it makes sense, that is, when the math and code can be made to look similar without adding confusion.

yungman said:
I read from someone that it's more fancy stuffs than really useful in real life programming.

A good rule of thumb is not to use operator overloading unless it actually is helpful and has a clear meaning. Remember, even modern C++ allows you to shoot yourself repeatedly in the foot if you insist, and overuse of operator overloading is a common C++ code smell.
 
  • Like
Likes yungman
  • #22
yungman said:
BTW, that's only calculation of magnitude, still need to know the vector part of it. 😊 can you overload that much? Must be very difficult to do this using overloading.

You have seen at least one example before :wink:. Let me make a fresh small example:

C++:
// C++ 17
#include <iostream>

using namespace std;

struct vec3 {
    double x, y, z;
    vec3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
    vec3 operator+(const vec3& rhs) const { return { x+rhs.x, y+rhs.y, z+rhs.z }; }
    vec3 operator*(double k) const { return { k*x, k*y, k*z }; }
};

vec3 operator*(double k, const vec3& rhs) { return rhs*k; }
ostream& operator<<(ostream& os, const vec3& v) { return os << "(" << v.x << " " << v.y << " " << v.z << ")"; }int main()
{
    vec3 r0(1, 2, 3), v0(2, 3, 4), a(1, 1, 1);
    double t = 2.0;
    vec3 r = r0 + t*v0 + 0.5 * a * t * t;
    cout << "r = " << r << endl;

    return 0;
}
 
  • Like
Likes yungman
  • #23
Filip Larsen said:
You have seen at least one example before :wink:. Let me make a fresh small example:

C++:
// C++ 17
#include <iostream>

using namespace std;

struct vec3 {
    double x, y, z;
    vec3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
    vec3 operator+(const vec3& rhs) const { return { x+rhs.x, y+rhs.y, z+rhs.z }; }
    vec3 operator*(double k) const { return { k*x, k*y, k*z }; }
};

vec3 operator*(double k, const vec3& rhs) { return rhs*k; }
ostream& operator<<(ostream& os, const vec3& v) { return os << "(" << v.x << " " << v.y << " " << v.z << ")"; }int main()
{
    vec3 r0(1, 2, 3), v0(2, 3, 4), a(1, 1, 1);
    double t = 2.0;
    vec3 r = r0 + t*v0 + 0.5 * a * t * t;
    cout << "r = " << r << endl;

    return 0;
}
I am looking a little into your program. Do you mean you can do overloading on struct also? It works just the same?

Thanks
 
  • #24
yungman said:
Do you mean you can do overloading on struct also? It works just the same?

If you are referring to the class definition starting with struct instead of class, then yes, don't let that confuse you. A struct is, in short, just a class where the default access (until you declare it to something else) is public, including any inheritance used. For class declarations the default access is private, so you have to use the public keyword to change.

For instance, in the example below the apple and orange class are effectively defined with the same access, i.e. public:

C++:
struct apple : fruit {
    void eat();
};

class orange : public fruit {
public:
    void eat();
}

Regarding if it is a good idea to use struct or class, it is just a (half-automatic) habit of mine to use struct for small examples where everything is public to indicate a simple value class where nothing is hidden. For more involved classes with hidden state it is by far recommended and common practice to define it using class.
 
  • Like
Likes yungman
  • #25
Are you determine to stop me from studying chapter 15?? 😊 😊 :biggrin:

I have question in comments. I want to verify line 8 is constructor with default value of all 0, but then just x=x, y=y, z=z from input.
C++:
// C++ 17
#include <iostream>

using namespace std;

struct vec3 {
    double x, y, z;

    vec3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
//Constructor  vec3(x=0,y=0,z=0){ x = x; y=y;z=z;}
    vec3 operator+(const vec3& rhs) const { return { x+rhs.x, y+rhs.y, z+rhs.z }; }
    vec3 operator*(double k) const { return { k*x, k*y, k*z }; }
};

vec3 operator*(double k, const vec3& rhs) { return rhs*k; }
ostream& operator<<(ostream& os, const vec3& v) { return os << "(" << v.x << " " << v.y << " " << v.z << ")"; }int main()
{// are r0, v0,a are numbers? what? integer or float?
    vec3 r0(1, 2, 3), v0(2, 3, 4), a(1, 1, 1); //declare 3 object of vec3?
    double t = 2.0;
    vec3 r = r0 + t*v0 + 0.5 * a * t * t;//declare r is object of vec3 where vec3 r = ...
    cout << "r = " << r << endl;

    return 0;
}

Thanks
EDIT:

I am missing something, vec3 consists of x, y, z all separate numbers. How can vec3 r = r0 + t*v0 + 0.5 * a * t * t ? This implies object r is a single number after solving r0, v0 and a.
 
Last edited:
  • #26
yungman said:
I have question in comments.

Line 9 (of your commented code block): the constructor notation : x(x), y(y), z(z) is member initialization, so the member variable x is initialized with the formal constructor parameter x. This means the matched member constructor is called. If you do as on (your) line 10 then the members are first default constructed (which for doubles means not initialized) and then they are assigned a value. If you are confused about the repeated name, then note constructor in line 9 could also be written as, say, vec3(double xi = 0, double yi = 0, double zi = 0) : x(xi), y(yi), z(zi) {}.

Line 21 defines three vec3 instances, r0, v0 and a, and uses constructor arguments to initialize their x, y, z member with values. If the construct arguments had been left out the coordinates would have been initialized to 0 due to the default values in the constructor. The values themselves are written as integers, but C++ will implicit convert these values to doubles when matching which constructor to use.

Line 23: Not sure what your question is, but r is defined and initialized with the result of the calculation.
 
  • #27
yungman said:
I am missing something, vec3 consists of x, y, z all separate numbers. How can vec3 r = r0 + t*v0 + 0.5 * a * t * t ? This implies object r is a single number after solving r0, v0 and a.
Look at this code:
C++:
vec3 r = r0 + t*v0 + 0.5 * a * t * t
The only way you can think that r is a 'single number' is if you do not understand the significance of vec3 at the beginning of the line. What do you think that does here?
 
  • Like
Likes Vanadium 50
  • #28
jtbell said:
As a physicist, I would much rather be able to program an equation such as $$\vec r = {\vec r}_0 + {\vec v}_0 t + 0.5 {\vec a} t^2$$ as
C++:
r = r0 + v0 * t + 0.5 * a * t^2
than as something like
C++:
r = vsum (vsum (r0, vsum (vmul (v0, t), 0.5 * a * pow (t, 2))))

I would make one change - I would much rather be able to maintain code...

You write code once. But you will need to modify it (or debug it) many times. It's better to optimize code for ease of reading than ease of writing. Your example does both. Clarity of intent is the key.

PS What's that XOR doing in t^2?
 
  • #29
Vanadium 50 said:
PS What's that XOR doing in t^2?
Good question! I must have been thinking of some other language that uses '^' for exponentiation. :oops:
 
  • #30
jtbell said:
C++:
r = vsum (vsum (r0, vsum (vmul (v0, t), 0.5 * a * pow (t, 2))))
Oops, a is a vector (see the original equation), so that should actually be something like
C++:
r = vsum (vsum (r0, vsum (vmul (v0, t), vmul (a, 0.5 * pow (t, 2)))))
This assumes of course that vsum() and vmul() return vectors, which is easily done in C++.

Back when I was a grad student about 40 years ago, I was doing this sort of thing in Fortran, which doesn't (or at least didn't) allow returning arrays from functions like that. I had a library of subroutines (void functions in C/C++) like vsum(a, b, sum) that returned a vector result as an argument. I couldn't combine all the calculations above into a single statement. I could have done something like
Fortran:
vmul (v0, t, term2)
vmul (a, 0.5*t**2, term3)
vsum (r0, term2, r)
vsum (r, term3, r)
...but it was easier to do it component by component in a do-loop:
Fortran:
do k = 1, 3
    r(k) = r0(k) + v0(k) * t + 0.5 * a(k) * t**2
end do
 
  • #31
jtbell said:
Good question! I must have been thinking of some other language that uses '^' for exponentiation.

Why not overload ^ to mean exponentiation?
Hint: It doesn't work.
Hint: It's subtle.
Hint: It's so subtle it's likely to work in tests but not in real code.
 
  • #32
yungman said:
But you still need a lot of work to overload this in the program just to make it look better. Not to mention it is definitely extra steps to do the over loading and more chance to make mistakes.
You're missing a couple of important points here.
First, the work of writing an overloaded operator happens once, but once done, it can be used many times. When you overload an operator, you are in essence extending the language, allowing it do some operation that isn't part of the language definition.
Second, the overloaded operator doesn't just make things look better - they allow code that uses the operator to be more natural, with the potential benefit of code that is less prone to errors. For example, if AddrBkA and AddBkB are directories, having an overloaded operator+() could allow a user to write AddrBkA + AddrBkB as an expression that would merge two address books.
Another point that you're missing is that their are hierarchies of programmers. At the lowest level are programmers who use existing libraries to create applications. At a higher level are those who create libraries and classes that others can use. In your case you have been wearing both hats, so the distinction isn't clear: the application developer who writes main(), and the class designer/implementer.
yungman said:
BTW, that's only calculation of magnitude, still need to know the vector part of it. 😊 can you overload that much? Must be very difficult to do this using overloading.
Not at all. And you have seen numerous examples in this thread.
yungman said:
I am missing something, vec3 consists of x, y, z all separate numbers. How can vec3 r = r0 + t*v0 + 0.5 * a * t * t ? This implies object r is a single number after solving r0, v0 and a.
No, this is not so. Already pointed out - the overloaded operator+() in the example allows the program to calculate ##\vec v = \vec a + \vec b##. What is returned is a vector. You apparently missed that the result object r was declared to be of type Vec3.
For the example shown it would also have been convenient to overload the * operator, to allow multiplication of a Vec3 object by a scalar. (In the assignment statement above, t and 0.5 are scalars, floating point numbers in this case.)
 
Last edited:
  • Like
Likes Vanadium 50
  • #33
It might be worth pointing out that "cout << data" uses an overloaded operator.
 
  • #34
yungman said:
How can vec3 r = r0 + t*v0 + 0.5 * a * t * t ?
It would be useful for you to go back and review variable declarations. In my version of Gaddis, this is at the very beginning of the book - Ch. 1 page 12.
 
  • Love
  • Like
Likes pbuk and Vanadium 50
  • #35
Vanadium 50 said:
Hint: It's so subtle it's likely to work in tests but not in real code.

Hint: There are certain rules for operators that remains fixed even when overloaded, which can trick people into shooting themselves in the foot, especially for expressions containing a mix of operators. Overloading operator^ to mean exponentiation is a prime example.
 

Similar threads

  • Programming and Computer Science
2
Replies
66
Views
4K
  • Programming and Computer Science
2
Replies
53
Views
3K
  • Programming and Computer Science
Replies
15
Views
2K
  • Programming and Computer Science
2
Replies
36
Views
3K
  • Programming and Computer Science
Replies
25
Views
2K
  • Programming and Computer Science
Replies
12
Views
1K
  • Programming and Computer Science
Replies
23
Views
2K
  • Programming and Computer Science
Replies
30
Views
2K
  • Programming and Computer Science
Replies
4
Views
784
  • Programming and Computer Science
Replies
12
Views
1K
Back
Top