|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Hi all;
I want to define an array of objects and initialize them, but I don't know how I could do that simply. I have searched over net, and have found a few solutions. Does anybody has a better, simple solution? Suppose there is a Foo class that has const member. class Foo { public: Foo(int, int); ~Foo(); private: const int ID; double int var; }; First method: Foo objects [MAX] = {Foo(0,1),Foo(1,2),Foo(2,3)}; // This one requires copy constructor, but I have const members, so it doesn't work for me. Second method: std::vector<Foo> objects; objects[0] = * (new Foo(0,1)); objects[1] = * (new Foo(1,2)); objects[2] = * (new Foo(2,3)); //This one solves problem of const members, but I dont want to use vector. I want to initialize the array as following, but it doesn't work. Foo objects[MAX] = {{0,1},{1,2},{2,3}}; Thanks yatko |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
* yatko:
> Hi all; > > I want to define an array of objects and initialize them, but I don't > know how I could do that simply. I have searched over net, and have > found a few solutions. Does anybody has a better, simple solution? > > Suppose there is a Foo class that has const member. > > class Foo > { > public: > Foo(int, int); > ~Foo(); > > > private: > const int ID; In general it's a good idea to reserve all uppercase names for macros. Using them for constants is a Java'ism. Leads to problems in C++. > double int var; There's no "double int" type in C++. > }; > > First method: > > Foo objects [MAX] = {Foo(0,1),Foo(1,2),Foo(2,3)}; This method works nicely. > // This one requires copy constructor, but I have const members, so it > doesn't work for me. It's opposite: the method below requires copy constructor, while the one above doesn't. > Second method: > > std::vector<Foo> objects; > > objects[0] = * (new Foo(0,1)); > objects[1] = * (new Foo(1,2)); > objects[2] = * (new Foo(2,3)); > > //This one solves problem of const members, but I dont want to use > vector. This doesn't work for const members. > I want to initialize the array as following, but it doesn't work. > > Foo objects[MAX] = {{0,1},{1,2},{2,3}}; Works OK. Post actual code that doesn't work (see the FAQ item how to get with Code That Does Not Work). Cheers, & hth., - Alf -- A: Because it messes up the order in which people normally read text. Q: Why is it such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail? |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
yatko wrote:
> I want to define an array of objects and initialize them, but I don't > know how I could do that simply. I have searched over net, and have > found a few solutions. Does anybody has a better, simple solution? > > Suppose there is a Foo class that has const member. > > class Foo > { > public: > Foo(int, int); > ~Foo(); > > > private: > const int ID; > double int var; There is no such type as "double int". > }; > > First method: > > Foo objects [MAX] = {Foo(0,1),Foo(1,2),Foo(2,3)}; > > // This one requires copy constructor, but I have const members, so it > doesn't work for me. Why is that? Does the compiler complain? (beyond 'double int', I mean) > Second method: > > std::vector<Foo> objects; > > objects[0] = * (new Foo(0,1)); > objects[1] = * (new Foo(1,2)); > objects[2] = * (new Foo(2,3)); > > //This one solves problem of const members, but I dont want to use > vector. No, it does not solve the "problem of const members". Putting your objects in a vector requires the presence of the copy constructor as well. Not to mention that you need to use 'push_back' instead of assigning since elements objects[i] do not exist unless you give the vector some substance (and declaring it does not give substance, not even empty space). Not to mention a memory leak (actually three memory leaks). > I want to initialize the array as following, but it doesn't work. > > Foo objects[MAX] = {{0,1},{1,2},{2,3}}; Correct. Brace-enclosed initialisers don't work for classes with parameterized constructors like yours. You might want to consider generating IDs from a static function; that way you don't have to provide any and the constructor that takes one argument could get/generate the ID automatically. Also, please get into the habit of stating the *requirements*, not showing non-working solutions, if you want in class design. V -- Please remove capital 'A's when replying by e-mail I do not respond to top-posted replies, please don't ask |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On Feb 21, 8:49 am, "Alf P. Steinbach" <al...@start.no> wrote:
> > In general it's a good idea to reserve all uppercase names for macros. > Using them for constants is a Java'ism. Leads to problems in C++. Isn't it more of a C'ism? As in #define MAX ...? |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
* dave_mikesell@fastmail.fm:
> On Feb 21, 8:49 am, "Alf P. Steinbach" <al...@start.no> wrote: > >> In general it's a good idea to reserve all uppercase names for macros. >> Using them for constants is a Java'ism. Leads to problems in C++. > > Isn't it more of a C'ism? As in #define MAX ...? No. The Java convention (probably) stems from the C convention to use all uppercase for macros. In early C one had to use macros for constants, so constants also typically had all uppercase names. But it's been some years since 1972, and C++ gives the ability to define constants without using macros. Since macros don't respect scopes it's generally not a good idea to let non-macro names enter that "namespace" in C++ (note: Java doesn't have this problem, because Java doesn't have a preprocessor). Cheers, & hth., - Alf -- A: Because it messes up the order in which people normally read text. Q: Why is it such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail? |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
Hi guys;
Sorry for silly 'double int' type mistake, I know that there is no such type, too. I just made mistake when writing the class definition to the group. Anyway, now you can find actual codes. These are Variable and ReaedersNWriters classes. As you can see, I have defined a const member mode , takes values of BLOCKING, TIMED_WAIT, NONBLOCKING , in ReadersNWriters class. namespace Monitor{ template <class DataType> class Variable : public ReadersNWriters { public: Variable(WaitingMode); ~Variable(); bool Read(DataType&); bool Write(const DataType&); private: DataType data; boost::mutex enter; }; } class ReadersNWriters { protected: typedef boost::mutex::scoped_lock scoped_lock; ReadersNWriters(WaitingMode); ~ReadersNWriters(); bool BeginRead(scoped_lock&); void EndRead(void); bool BeginWrite(scoped_lock&); void EndWrite(void); private: const WaitingMode mode; int waitingReaders; int nReaders; int waitingWriters; int nWriters; boost::condition canRead; boost::condition canWrite; }; All I want to do is defining an array of Monitor::Variable<int> objects and initializing their const mode as TIMED_WAIT, BLOCKING or NONBLOCKING. Monitor::Variable<int> datad[] = {TIMED_WAIT, NONBLOCKING, BLOCKING, TIMED_WAIT}; // Compiler doesn't give any error, here But it complains like that: ------------------------------------------------------------ **** Build of configuration Debug for project test **** make all Building file: ../main.cpp Invoking: GCC C++ Compiler g++ -I/usr/local/boost_1_34_1 -I"/home/oktay/workspace/test" -O0 -g3 - Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp" .../main.cpp: In function 'void writer_list(int)': .../main.cpp:237: warning: unused variable 'data1' .../main.cpp:239: warning: unused variable 'data3' .../main.cpp:240: warning: unused variable 'data4' /usr/local/boost_1_34_1/boost/noncopyable.hpp: In copy constructor 'boost::condition::condition(const boost::condition&)': /usr/local/boost_1_34_1/boost/noncopyable.hpp:27: error: 'boost::noncopyable_::noncopyable::noncopyable(con st boost::noncopyable_::noncopyable&)' is private /usr/local/boost_1_34_1/boost/thread/condition.hpp:79: error: within this context /usr/local/boost_1_34_1/boost/noncopyable.hpp: In copy constructor 'boost::detail::condition_impl::condition_impl(con st boost::detail::condition_impl&)': /usr/local/boost_1_34_1/boost/noncopyable.hpp:27: error: 'boost::noncopyable_::noncopyable::noncopyable(con st boost::noncopyable_::noncopyable&)' is private /usr/local/boost_1_34_1/boost/thread/condition.hpp:35: error: within this context /usr/local/boost_1_34_1/boost/thread/condition.hpp: In copy constructor 'boost::condition::condition(const boost::condition&)': /usr/local/boost_1_34_1/boost/thread/condition.hpp:79: note: synthesized method 'boost::detail::condition_impl::condition_impl(con st boost::detail::condition_impl&)' first required here .../ReadersNWriters.h: In copy constructor 'ReadersNWriters::ReadersNWriters(const ReadersNWriters&)': .../ReadersNWriters.h:11: note: synthesized method 'boost::condition::condition(const boost::condition&)' first required here .../Variable.h: In copy constructor 'Monitor::Variable<int>::Variable(const Monitor::Variable<int>&)': .../Variable.h:13: note: synthesized method 'ReadersNWriters::ReadersNWriters(const ReadersNWriters&)' first required here /usr/local/boost_1_34_1/boost/noncopyable.hpp: In copy constructor 'boost::mutex::mutex(const boost::mutex&)': /usr/local/boost_1_34_1/boost/noncopyable.hpp:27: error: 'boost::noncopyable_::noncopyable::noncopyable(con st boost::noncopyable_::noncopyable&)' is private /usr/local/boost_1_34_1/boost/thread/mutex.hpp:35: error: within this context .../Variable.h: In copy constructor 'Monitor::Variable<int>::Variable(const Monitor::Variable<int>&)': .../Variable.h:13: note: synthesized method 'boost::mutex::mutex(const boost::mutex&)' first required here .../main.cpp: At global scope: .../main.cpp:27: note: synthesized method 'Monitor::Variable<int>::Variable(const Monitor::Variable<int>&)' first required here make: *** [main.o] Error 1 ---------------------------------------------------------------- > In general it's a good idea to reserve all uppercase names for macros. > Using them for constants is a Java'ism. Leads to problems in C++. I really don't what Java'ism, C'ism or C++'ism are, and I want to learn coding conventions about C++, if you could suggest me a good tutorial, ebook etc. Thanks yatko |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On Feb 21, 10:02 am, yatko <yatkonal...@gmail.com> wrote:
> I really don't what Java'ism, C'ism or C++'ism are, and I want to > learn coding conventions about C++, if you could suggest me a good > tutorial, ebook etc. I don't know that there are agreed upon conventions regarding style, but there are plenty of books written about using C++ the Right Way (tm). http://www.parashift.com/c++-faq-lit....html#faq-28.5 |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
* dave_mikesell@fastmail.fm:
> On Feb 21, 10:02 am, yatko <yatkonal...@gmail.com> wrote: > >> I really don't what Java'ism, C'ism or C++'ism are, and I want to >> learn coding conventions about C++, if you could suggest me a good >> tutorial, ebook etc. > > I don't know that there are agreed upon conventions regarding style, > but there are plenty of books written about using C++ the Right Way > (tm). > > http://www.parashift.com/c++-faq-lit....html#faq-28.5 Unfortunately it seems the FAQ hasn't been updated for a while. For the OP's specific question, a good book about conventions is "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" by Herb Sutter and Andre Alexandrescu. They have some apparently silly advice about reinterpret_cast, but apart from that very very solid (unfortunately I don't have this book). Cheers, & hth., - Alf -- A: Because it messes up the order in which people normally read text. Q: Why is it such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail? |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
Alf, Dave
I appreciate for references, thanks very much. yatko |
|
|
|
#10 |
|
Messages: n/a
Hébergeur: |
Alf P. Steinbach wrote:
> In early C one had to use macros for constants, > so constants also typically had all uppercase names. > ... Just as a side note, aside from enums, modern C still relies on macros for true constants (as in "constant expressions"). Even in C99 const-qualified objects are still not "constants", i.e. they can't be used in constant expressions. -- Best regards, Andrey Tarasevich |
|
|
|
#11 |
|
Messages: n/a
Hébergeur: |
On Feb 21, 7:16 am, yatko <yatkonal...@gmail.com> wrote:
> Hi all; > > I want to define an array of objects and initialize them, but I don't > know how I could do that simply. I have searched over net, and have > found a few solutions. Does anybody has a better, simple solution? > > Suppose there is a Foo class that has const member. > > class Foo > { > public: > Foo(int, int); > ~Foo(); > > private: > const int ID; > double int var; > > }; > > First method: > > Foo objects [MAX] = {Foo(0,1),Foo(1,2),Foo(2,3)}; > > // This one requires copy constructor, but I have const members, so it > doesn't work for me. > > Second method: > > std::vector<Foo> objects; > > objects[0] = * (new Foo(0,1)); > objects[1] = * (new Foo(1,2)); > objects[2] = * (new Foo(2,3)); > > //This one solves problem of const members, but I dont want to use > vector. > > I want to initialize the array as following, but it doesn't work. > > Foo objects[MAX] = {{0,1},{1,2},{2,3}}; > > Thanks > > yatko the way you have it should work exept you can't change a constant after it is inisialized and you should write it: Foo objects[MAX] = {Foo(0,1),Foo(1,2),Foo(2,3)}; someone else praly suggested this, but just the same, hope this s |
|
|
|
#12 |
|
Messages: n/a
Hébergeur: |
On Feb 21, 3:49 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * yatko: > > I want to define an array of objects and initialize them, > > but I don't know how I could do that simply. I have searched > > over net, and have found a few solutions. Does anybody has a > > better, simple solution? > > Suppose there is a Foo class that has const member. > > class Foo > > { > > public: > > Foo(int, int); > > ~Foo(); > > private: > > const int ID; > > double int var; > > }; > > First method: > > Foo objects [MAX] = {Foo(0,1),Foo(1,2),Foo(2,3)}; > This method works nicely. For his class above, yes. As he later indicates, he was holding out on us---his actual class contains a boost::mutex, which isn't copiable. > > // This one requires copy constructor, but I have const members, so it > > doesn't work for me. > It's opposite: the method below requires copy constructor, > while the one above doesn't. No. They both require the copy constructor. To begin with, aggregate initialization is copy initialization. And even if it weren't, his initialization expression in both cases has the type Foo, so the copy constructor will be called. Of course, the presence of a const member doesn't cause any problems for the copy constructor. His class above has a perfectly good, compiler generated copy constructor. > > Second method: > > std::vector<Foo> objects; > > objects[0] = * (new Foo(0,1)); > > objects[1] = * (new Foo(1,2)); > > objects[2] = * (new Foo(2,3)); > > //This one solves problem of const members, but I dont want to use > > vector. > This doesn't work for const members. Right, because is uses assignment, and not copy construction. > > I want to initialize the array as following, but it doesn't work. > > Foo objects[MAX] = {{0,1},{1,2},{2,3}}; > Works OK. Huh? Foo is not an aggregate, and so cannot be initialized using aggregate initialization. To initialize the array, you must provide a list of Foo, or of things which can be implicitly converted to Foo---since Foo doesn't have a converting constructor, there isn't anything which can be converted to Foo. -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
|
|
#13 |
|
Messages: n/a
Hébergeur: |
On Feb 21, 4:30 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * dave_mikes...@fastmail.fm: > > On Feb 21, 8:49 am, "Alf P. Steinbach" <al...@start.no> wrote: > >> In general it's a good idea to reserve all uppercase names > >> for macros. Using them for constants is a Java'ism. Leads > >> to problems in C++. > > Isn't it more of a C'ism? As in #define MAX ...? > No. > The Java convention (probably) stems from the C convention to > use all uppercase for macros. In early C one had to use > macros for constants, so constants also typically had all > uppercase names. But it's been some years since 1972, and C++ > gives the ability to define constants without using macros. It was the convention in early C++ as well. We've learned better since:-). A small historical note: in early C, I'm not sure that the conventions were that fixed. There was a convention that macros which could be used as a function obeyed the same naming conventions as a function. There was also a convention that manifest constants were all caps---and manifest constants were (and still are) implemented by means of a macro in C. Beyond that, it was pretty open---putc was almost always a macro, for example, and arguable was distinct from a function, because it evaluated its FILE* argument twice. (Exactly how close to a function "used as a function" implied was generally not stated.) When I started using C++ professionally, the convention was still generally all caps for constants. But the first questions were being raised; Jon Bentley (I think) had a quote along the lines of "one man's constant is another man's variable", and real applications were encountering the case where evolution caused a "constant" to be read from a configuration file. I remember being among the first in my company to argue against all caps for constants. Of course, that was all a very long time ago (for this profession, anyway). I'd say that the all cap's for macros has been pretty well established for at least ten years now, maybe more. And we have a case of Java enshrining something that was already beginning to be recognized as a mistake in C++. > Since macros don't respect scopes it's generally not a good > idea to let non-macro names enter that "namespace" in C++ > (note: Java doesn't have this problem, because Java doesn't > have a preprocessor). But even in Java, one man's constants are another man's variables. And the Java library itself doesn't adhere strictly to the rule (probably because some constants later became variables, and vice versa---although it's hard to imagine that Color::red was ever anything but a constant). -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
|
|
#14 |
|
Messages: n/a
Hébergeur: |
* James Kanze:
> On Feb 21, 3:49 pm, "Alf P. Steinbach" <al...@start.no> wrote: >> * yatko: > >>> I want to define an array of objects and initialize them, >>> but I don't know how I could do that simply. I have searched >>> over net, and have found a few solutions. Does anybody has a >>> better, simple solution? > >>> Suppose there is a Foo class that has const member. > >>> class Foo >>> { >>> public: >>> Foo(int, int); >>> ~Foo(); > >>> private: >>> const int ID; > >>> double int var; > >>> }; > >>> First method: > >>> Foo objects [MAX] = {Foo(0,1),Foo(1,2),Foo(2,3)}; > >> This method works nicely. > > For his class above, yes. As he later indicates, he was holding > out on us---his actual class contains a boost::mutex, which > isn't copiable. > >>> // This one requires copy constructor, but I have const members, so it >>> doesn't work for me. > >> It's opposite: the method below requires copy constructor, >> while the one above doesn't. > > No. They both require the copy constructor. To begin with, > aggregate initialization is copy initialization. You're right, I didn't know that. It's not very logical and MSVC 7.1 handles lack of copy constructor fine (which is logical, it's not technically needed except when initializer is an object of a derived class, only formally, and only a very obnoxious compiler would actually do that unnecessary copying!). Though now that you mentioned it, I checked and g++ detects the formal problem, and Comeau does, and I found it hidden away in §12.6.1/2 and also §8.5/12. Have you any idea why on earth that rule is there, what problem it's meant to us avoid? I can understand that it s with the standard-writer's internal problem of specifying the notation, the special case of derived class object as initializer. But, it's completely in breach of the "don't pay for what you're not using" principle of C++, and the C++0x fix of 'T const&' argument semantics. So, it looks like a defect to me: if I want that array of non-copy-constructible objects, the compiler should let me have it (without resorting to placement new), as MSVC does... [snip] >>> I want to initialize the array as following, but it doesn't work. > >>> Foo objects[MAX] = {{0,1},{1,2},{2,3}}; > >> Works OK. > > Huh? Sorry. I didn't see that it was different. Again you're right. Cheers, - Alf -- A: Because it messes up the order in which people normally read text. Q: Why is it such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail? |
|
|
|
#15 |
|
Messages: n/a
Hébergeur: |
On Feb 22, 3:22 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * James Kanze: > > On Feb 21, 3:49 pm, "Alf P. Steinbach" <al...@start.no> wrote: > >> * yatko: > You're right, I didn't know that. It's not very logical and > MSVC 7.1 handles lack of copy constructor fine (which is > logical, it's not technically needed except when initializer > is an object of a derived class, only formally, and only a > very obnoxious compiler would actually do that unnecessary > copying!). Though now that you mentioned it, I checked and > g++ detects the formal problem, and Comeau does, and I found > it hidden away in §12.6.1/2 and also §8.5/12. > Have you any idea why on earth that rule is there, what > problem it's meant to us avoid? Not really. The real question, to begin with, is why there are two types of initialization. I'm pretty sure that there must be a strong reason for that, because it did make a lot of extra work for the committee. It would have been a lot easier to just say that initialization calls the corresponding constructor, period. (There is some argument in that you might not want to support conversions, e.g. of function arguments. But the distinction predates explicit, so that aspect wasn't what motivated it.) Once you accept that: T obj( init ) ; and T obj = init ; have different semantics, of course: the reason aggregate initialization has the semantics of the second is because its syntax has an =. I know, it's not a very good reason at all. But I can't think of another one. Fundamentally, I'm with you on this; it would seem logical to me that something like: T array[2] = { init1, init2 } ; be the equivalent of: T array[0]( init1 ) ; T array[1]( init2 ) ; as far as initialization is concerned. I wasn't able to find anything about this in Stroustrup's DEC++, either (but maybe I just didn't know where to look). The distinction between the two types of initialization is present in the ARM, but only for class types; the ARM doesn't say which type of initialization applies to classes in aggregates when aggregate initialization is used. I'd suggest we take it up in csc++, except that that group doesn't seem to be any more. > I can understand that it s with the standard-writer's > internal problem of specifying the notation, the special case > of derived class object as initializer. But, it's completely > in breach of the "don't pay for what you're not using" > principle of C++, and the C++0x fix of 'T const&' argument > semantics. > So, it looks like a defect to me: if I want that array of > non-copy-constructible objects, the compiler should let me > have it (without resorting to placement new), as MSVC does... It's not a defect in the formal sense: something that is poorly specified, contradictory, or doesn't correspond to the voted intent. I would consider it perhaps a poor decision, however. In practice, I don't think it a big issue. Agglomerates don't usually make sense except with value types, value types should support copy, and the compiler will optimize the copy out, so the net effect is what we want. Still, it isn't pretty. -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
![]() |
| Outils de la discussion | |
|
|