1

For a constructor with multiple arguments...

For example:

class C {
public:
    C(int a=1, int b=2){ cout << a << ", " << b << "\n"; }
}

int main(){
    C a(10), b = 20;
}

output:
10, 2
20, 2

How do I just assign value to the 2nd parameter? So that I can get "1, 20" without knowing the default values? Or is that that I must always assign value to the argument that precedes before I can use the arguments behind?

And how do I implicitly assign all the parameters? If I can't do that, why? For the above example (as I am new to C++), I once thought I would get "10, 20" as output instead.

yeeen
  • 4,911
  • 11
  • 52
  • 73

4 Answers4

2

Or is that that I must always assign value to the argument that precedes before I can use the arguments behind?

Yes. Otherwise, how is the compiler supposed to know which argument should be used for which parameter?

However, there are ways to accomplish this. For example,

struct C {
    enum { DefaultA = 1, DefaultB = 2 };
    C(int a = DefaultA, int b = DefaultB) { /* ... */ }
};

C object(C::DefaultA, 20);

Or, if you have a lot of parameters with different "defaults:"

struct CParams {
    int a, b;
    CParams() : a(1), b(2) { }
};

struct C {
    C(CParams x) { /* ... */ }
};

CParams params;
params.b = 20;
C object(params);
James McNellis
  • 348,265
  • 75
  • 913
  • 977
1

C++ doesn't support named arguments. You have to specify the first one.

Also, the variable name b from the main function is completely separate from the b in the constructor definition. There's no relationship whatsoever implied by the naming.

Foo Bah
  • 25,660
  • 5
  • 55
  • 79
1

I had the same thought (Convienient C++ struct initialisation -- perhaps you find something you like better there) some time ago, but just now, reading your question, I thought of a way to actually accomplish this. But it is quite some extra code, so the question remains if it is actually worth it. I just implemented it very sketchy and I am not proud of my choice of names (I usually don't use _ but it's late). Anyway, this is how you can do it:

#include <iostream>

struct C_members {
  int a;
  int b;
  C_members(int _a, int _b) : a(_a), b(_b) {}
};
class C_init {
  public:
    virtual C_members get(C_members init) const {
      return init;
    }
};
class C_a : public C_init {
  private:
    int a;
  public:
    C_a(int _a) : a(_a) {}
    C_members get(C_members init) const {
      init.a = a;
      return init;
    }
};
class C_b : public C_init {
  private:
    int b;
  public:
    C_b(int _b) : b(_b) {}
    C_members get(C_members init) const {
      init.b = b;
      return init;
    }
};
class C : private C_members {
  private:
    static const C_members def;
  public:
    C(C_init const& ai = C_init(), C_init const& bi = C_init()) : C_members(ai.get(bi.get(def)).a, bi.get(ai.get(def)).b) {
      std::cout << a << "," << b << std::endl;
    }
};

const C_members C::def(1,2); // default values

// usage:
int main() {
  C c1(C_b(77)); // 1,77
  C c2(C_a(12)); // 12,2
  C c3(C_b(5),C_a(6)); // 6,5
  return 0;
}

There is a lot of stuff that can be improved (with templates (for code reduction) and with const refs in the get method), but you get the idea.

As a bonus feature, you almost have the pimpl idiom implemented (very little effort is necessary to extend this to an actual pimpl design).

Community
  • 1
  • 1
bitmask
  • 32,434
  • 14
  • 99
  • 159
  • Does "a(a)" in "C_a(int a) : a(a) {}" means passing in the value of 'a' into the variable 'a' in C_members? – yeeen Sep 08 '11 at 08:02
  • No, `a(a)` means "take the value of the *argument* `a` and construct my *member* `a` with it". That's how initialisation are usually carried out for pass-through values (at least, that's how *I* like to do it). – bitmask Sep 08 '11 at 13:34
  • I changed some variable names, so it is more obvious what's going on. – bitmask Sep 08 '11 at 13:43
0

Usually in OOP, every object instance holds (and represents) a state. So the best way is to define an accessor functions such as void setB(int newBvalue); and also to hold b as a private member.

if "b" is shared among all the instances of the same object, consider to save a static variable.

Guy L
  • 2,824
  • 2
  • 27
  • 37