- Override - 11 Updates
- Polymorphism and std::copy - 5 Updates
- faster than c - 1 Update
Christopher Pisz <nospam@notanaddress.com>: Apr 20 05:54PM -0500 On 4/20/2015 5:24 PM, Stefan Ram wrote: SNIP > ::std::vector< ::std::unique_ptr< Fish >> w; > for( auto & f: v )w.push_back( f->clone() ); /* copying is here */ > for( auto & f: w )f->print(); } Still catching up on the C++11 standard. What do the override and final keywords actually accomplish? Is its only purpose to provide compiler errors if the base didn't have a matching virtual method signature? Or does it do something else, perhaps some kind of optimization? -- I have chosen to troll filter/ignore all subthreads containing the words: "Rick C. Hodgins", "Flibble", and "Islam" So, I won't be able to see or respond to any such messages --- |
Luca Risolia <luca.risolia@linux-projects.org>: Apr 21 01:06AM +0200 Il 20/04/2015 23:28, Paavo Helde ha scritto: > vector<std::shared_ptr<Fish>> vecOfFish; > vecOfFish.push_back(std::shared_ptr<Fish>(new Tuna())); > vecOfFish.push_back(std::shared_ptr<Fish>(new Carp())); Use std::make_shared() whenever possible. It's more efficient and more compact (in terms of both object and source code). In this case: vecOfFish.push_back(std::make_shared<Tuna>()); vecOfFish.push_back(std::make_shared<Carp>()); |
Melzzzzz <mel@zzzzz.com>: Apr 21 04:23AM +0200 On 21 Apr 2015 01:36:10 GMT > I wanted to make »print« public, but forgot to > make it public in »class Tuna«. > Is this good or bad style? Well, one can't call print on Tuna but can on Fish. I remember it was considered to be good style to make virtual functions private and call them from base class non virtual functions eg: class Base { public: void f() { virt(); } } private: virtual void virt()=0; }; class Derived : public Base { void virt() {} }; Derived d; d.f(); |
Victor Bazarov <v.bazarov@comcast.invalid>: Apr 21 12:03AM -0400 On 4/20/2015 7:06 PM, Luca Risolia wrote: > In this case: > vecOfFish.push_back(std::make_shared<Tuna>()); > vecOfFish.push_back(std::make_shared<Carp>()); Given 'class Derived : public Base {};', is 'shared_ptr<Derived>' convertible to 'shared_ptr<Base>'? Your suggestion seems to imply as much... V -- I do not respond to top-posted replies, please don't ask |
Ian Collins <ian-news@hotmail.com>: Apr 21 04:46PM +1200 Christopher Pisz wrote: > purpose to provide compiler errors if the base didn't have a matching > virtual method signature? Or does it do something else, perhaps some > kind of optimization? Mainly the former. It also provides a better form of documentation than prefixing virtual function overrides with "virtual" as required by some older coding standards I've sen. -- Ian Collins |
Paavo Helde <myfirstname@osa.pri.ee>: Apr 21 12:00AM -0500 Christopher Pisz <nospam@notanaddress.com> wrote in news:mh400q$r4o$1@dont- email.me: > purpose to provide compiler errors if the base didn't have a matching > virtual method signature? Or does it do something else, perhaps some > kind of optimization? The final keyword can be used for optimization as the compiler can potentially replace some virtual calls by non-virtual and maybe even inline them. However, I guess this is not the main reason because if this is possible it means that making the function virtual was not really necessary in the first place (at least not in this usage scenario). The override keyword is just for producing compiler errors, but it is immensely useful when refactoring a large code base. I guess final could also be useful in some kind of (more radical) refactoring. Cheers Paavo |
Paavo Helde <myfirstname@osa.pri.ee>: Apr 21 12:30AM -0500 ram@zedat.fu-berlin.de (Stefan Ram) wrote in news:private-20150421033347 > I wanted to make »print« public, but forgot to > make it public in »class Tuna«. > Is this good or bad style? Yes, you can have private virtual functions in C++. The access checks are done at compile time only and are based on the static type of the pointer/reference through which the virtual function is called. At run- time the program does not know or care any more if some vtable slot points to a private or non-private virtual function override. This is most useful if the access is uniformly private in all classes of the hierarchy. In your example (public in the base, private in derived) it is just a bit confusing and does not accomplish much. But according to the ideology of C++, a half-accidental language feature like this is not locked down just because there is no clear usage case or it could be potentially misused. Instead, the programmer is trusted to use or not use the features as he sees fit. Cheers Paavo |
legalize+jeeves@mail.xmission.com (Richard): Apr 21 03:29PM [Please do not mail me a copy of your followup] Luca Risolia <luca.risolia@linux-projects.org> spake the secret code >In this case: > vecOfFish.push_back(std::make_shared<Tuna>()); > vecOfFish.push_back(std::make_shared<Carp>()); Even better: if you just need a container of polymorphic objects use std::unique_ptr<T> and std::make_unique[*]. I see people over-usign shared_ptr when unique_ptr would suffice. [*] if your implementation doesn't yet have make_unique or unique_ptr, then consider using an alternative from boost. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
Luca Risolia <luca.risolia@linux-projects.org>: Apr 21 06:16PM +0200 On 21/04/2015 17:29, Richard wrote: >> vecOfFish.push_back(std::make_shared<Carp>()); > Even better: if you just need a container of polymorphic objects use > std::unique_ptr<T> and std::make_unique[*]. If it's better clearly depends on the real application. unique_ptr's are inadequate, if you need to copy the vector for some reasons. |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Apr 21 05:33PM +0100 On 21/04/2015 16:29, Richard wrote: [snip] > I see people over-usign shared_ptr when unique_ptr would suffice. > [*] if your implementation doesn't yet have make_unique or unique_ptr, > then consider using an alternative from boost. There is no alternative to unique_ptr in Boost as unique_ptr requires move semantics and Boost won't magically give you move semantics sausages. /Flibble |
Luca Risolia <luca.risolia@linux-projects.org>: Apr 21 08:22PM +0200 Il 21/04/2015 06:03, Victor Bazarov ha scritto: > Given 'class Derived : public Base {};', is 'shared_ptr<Derived>' > convertible to 'shared_ptr<Base>'? Yes, although they are not covariant. |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 21 01:36AM > virtual ::std::unique_ptr< Fish >clone() = 0; }; >class Tuna : public Fish >{ void print () override { puts( "Tuna" ); } ... >for( auto & f: w )f->print(); } I only now become aware of the fact that the »print« method of »Tuna« is called by the client, even though it is »privat« in »class Tuna«! Or does it »inherit« the »public«? I wanted to make »print« public, but forgot to make it public in »class Tuna«. Is this good or bad style? |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 21 03:13AM >>So, as the array is temporary, a pointer to its element can and will >>become dangling as far as I can see. >I thought the clarification (making the return value a constexpr) takes »constexpr« did not occur so far. A const& can extend the lifetime of a temporary, but it must be bound to it directly, not via a pointer. »::std::begin« does not accept an initialization list, only an array reference, so a temporary array will be created and the begin pointer of that array will be computed. The result is a pointer to the begin of that array. Then, that array will be destroyed. It is as if #include <initializer_list> #include <iostream> #include <ostream> struct array { array( ::std::initializer_list< int >const ){}; ~array(){ ::std::cout << "I, temporary array, destroyed\n"; } }; int * begin( array ){ return nullptr; } int main() { ::std::cout << "before\n"; const int * y = begin( { 1, 2, 3 }); /* this is like your code */ ::std::cout << "after\n"; ::std::cout << "y = " << y << '\n'; } before I, temporary array, destroyed after y = 0 > Certainly the generated code I've checked for a couple of >compilers shows the values being accessed from static data. When arguing about C++, the language, C++s, the implementations, are not authoritative. Or, as Bartosz Milewski puts it: »The fact that the program works has no relevance.« |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 21 05:12AM >Stefan Ram wrote: >18.9.3 Initializer list range access >template<class E> const E* begin(initializer_list<E> il) noexcept; I was not aware of this! Today it is specified as: template<class E> constexpr const E* begin(initializer_list<E> il) noexcept; Returns: il.begin(). . This copies the argument initializer list to the parameter il, but if the underlying array has static storage duration, then the pointer will /not/ dangle, indeed. |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 21 04:35PM >. This copies the argument initializer list to the parameter il, >but if the underlying array has static storage duration, >then the pointer will /not/ dangle, indeed. I think it's crucial whether the »underlying array« of an initializer list is a part of the initializer list or is referenced by the initializer list. When it is /referenced/ by the initializer list, the parameter will refer the same underlying array as the argument, and when this array has static storage duration, a pointer into it will not dangle. |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 21 04:43PM >If it's better clearly depends on the real application. unique_ptr's are >inadequate, if you need to copy the vector for some reasons. I just posted code in <deep-copy-20150421001620@ram.dialup.fu-berlin.de> that uses make_unique /and/ copies the vector. Also, it is written in herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ »When in doubt, prefer unique_ptr by default, and you can always later move-convert to shared_ptr if you need it.« |
Ian Collins <ian-news@hotmail.com>: Apr 21 04:36PM +1200 Stefan Ram wrote: > the begin pointer of that array will be computed. The result > is a pointer to the begin of that array. Then, that array will > be destroyed. It is as if 18.9.3 Initializer list range access template<class E> const E* begin(initializer_list<E> il) noexcept; 1 Returns: il.begin(). > { array( ::std::initializer_list< int >const ){}; > ~array(){ ::std::cout << "I, temporary array, destroyed\n"; } }; > int * begin( array ){ return nullptr; } So this always returns nullptr. > int main() > { ::std::cout << "before\n"; > const int * y = begin( { 1, 2, 3 }); /* this is like your code */ So this is equivalent to y = nullptr; > I, temporary array, destroyed > after > y = 0 int main() { std::cout << "before\n"; const int * y = std::begin( { 1, 2, 3 }); /* this is like your code */ std::cout << "after\n"; std::cout << "y = " << y << '\n'; } before after y = 0x8051294 -- Ian Collins |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment