> Do most professional C++ programmers utilize this style?
As far as the details go (placing of braces, spaces,
const int& ref vs.
int const &ref etc.), there are a wide variety of different styles in vogue.
One thing that is certain is that a professional programmer would tend to avoid raw pointers and explicit calls to new and delete. And might code a little more defensively (check for null pointer etc.).
> what is the advantage over the other using struct and class like I was doing?
This toy example too uses classes like you were doing; the only difference is that for reasons of brevity, the classes were not partitioned into their own components (header and cpp files).
> lets say two or more pets were given the same name, and would like both of them to respond?
No. In the code posted above, the function returns immediately once a pet with the name has spoken. To get all the pets with that name to speak, we would just continue iterating till the end.
Using smart pointers instead of smart pointers, and getting all the pets with the name to speak, the code would be something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
#include <iostream>
#include <string>
#include <cctype>
#include <vector>
#include <memory>
struct pet
{
explicit pet( std::string its_name ) : name(its_name) {}
virtual ~pet() = default ;
void speak() const { std::cout << name << ": " << sound() << "!\n" ; }
const std::string& its_name() const { return name ; }
std::string its_type() const { return type() ; }
// https://en.cppreference.com/w/cpp/memory/unique_ptr
// http://www.drdobbs.com/cpp/c11-uniqueptr/240002708
// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-newdelete
using pointer = std::unique_ptr<pet> ;
protected:
virtual std::string sound() const = 0 ;
virtual std::string type() const = 0 ;
const std::string name ;
};
struct dog : pet
{
using pet::pet ;
protected:
virtual std::string sound() const override { return "woof" ; }
virtual std::string type() const override { return "dog" ; }
};
struct cat : pet
{
using pet::pet ;
protected:
std::string sound() const override { return "meow" ; }
virtual std::string type() const override { return "cat" ; }
};
std::string& make_lower( std::string& str )
{
for( char& c : str ) c = std::tolower( (unsigned char)c ) ;
return str ;
}
std::vector<pet::pointer> make_pets()
{
std::cout << "Enter a list of pet type and pet name in the form <Dog|Cat Name>.\n"
<< "When you are finished enter <done>.\n";
std::vector<pet::pointer> all_pets ;
std::string type;
std::string name ;
while( std::cout << "Enter pet type and pet name (eg. Dog Fido or Cat Felix): " &&
std::cin >> type && make_lower(type) != "done" &&
std::cin >> name )
{
// https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
if( type == "cat" ) all_pets.push_back( std::make_unique<cat>(name) ) ;
else if( type == "dog" ) all_pets.push_back( std::make_unique<dog>(name) ) ;
else std::cout << "unsupported pet type\n" ;
}
return all_pets ;
}
// say hello to all pets with matching names
void say_hello( const std::vector<pet::pointer>& pets, std::string pet_name )
{
bool matched = false ;
// range based loop: http://www.stroustrup.com/C++11FAQ.html#for
for( const pet::pointer& ptr : pets )
{
if( ptr != nullptr )
{
std::string its_name = ptr->its_name() ;
// if( make_lower(its_name) == make_lower(pet_name) ) return ptr->speak() ;
if( make_lower(its_name) == make_lower(pet_name) )
{
ptr->speak() ; // don't return immediately, continue searching for more pets
matched = true ;
}
}
}
if( !matched ) std::cout << "did not find any pet with name '" << pet_name << "'\n" ;
}
void speak_with_pets( const std::vector<pet::pointer>& pets )
{
std::cout << "\nSay hello to a specific pet by addressing its name. 'Hello <pet name>' \n"
<< "when you are done say 'Goodbye'\n";
std::string greeting ;
std::string name ;
while( std::cout << "Enter greeting (eg. Hello Fido or Hello Everybody): " &&
std::cin >> greeting && make_lower(greeting) != "goodbye" &&
std::cin >> name )
{
if( greeting != "hello" ) std::cout << "invalid input\n" ;
else if( make_lower(name) == "everybody" ) // say hello to all
{
for( const pet::pointer& ptr : pets ) if( ptr != nullptr ) ptr->speak() ;
}
else say_hello( pets, name ) ; // say hello to pets with this name
}
}
int main()
{
const auto all_pets = make_pets() ;
std::cout << "the pets are:\n--------\n" ;
for( const auto& ptr : all_pets )
std::cout << ptr->its_name() << " (" << ptr->its_type() << ")\n" ;
speak_with_pets(all_pets) ;
}
|