Avoiding object slicing within abstractions and their derivations
Allowing a Shape to be assigned to a circle does not sound like it is very safe. I suppose there are situations where it can be used but I would advice against it in the general case
Also I would use Curiously Recurring Template Pattern to get around having to write the assignment operator-er in every derived class.
class Shape
{ // STUFF
};

template&lt;typename T&gt;
class ShapeCopyable: public Shape
{
    T&amp; operator=(const Shape&amp; s)
    {
        T const&amp; c = dynamic_cast&lt;T const&amp;&gt;(s);  // Throws on bad cast.
        assign(c);

        return *this;
    }
};
class Circle: public ShapeCopyable&lt;Circle&gt;
{
    // Stuff
};

In addition to what @Chris Jester-Young covered (so everything he said):
The Base class of a hierarchy with virtual methods should also have a virtual destructor. Otherwise you are going to start having issues with memory management when you start dynamically creating objects on the fly.
class Shape {
public:
    virtual ~Shape() {}

Don't define the copy constructor or assignment operator if nothing special needs to be done. Let the compiler generated version do the work for you. Unless you have something special in the destructor or have RAW pointer members this is unlikely. PS you should not have RAW pointer members either.
    // Remove this:
    virtual Shape&amp; operator=(const Shape&amp; s);

Don't like getters/setters. They break encapsulation and expose the internal implementation of the object. You should consider why you need to pass the state of the object out (is the function that uses the values really a member function).
Interactions on the object should usually be done internally to the object. This will get rid of most of your needs for getters and setters. If you still have a need after the analysis fine.
    // Don't like them.
    // Make but sometimes you need them but minimze your
    // exposure by using methods that manipulate the object rather
    // than moving the manipulation to an external actor.
    std::string getName() { return name; }
            int getEdges() { return edges; }
            int getRadius() { return radius; }
           void setRadius(int r) { radius = r; }

A vector of pointers. Red flag who owns the pointers.
    std::vector&lt;Shape*&gt; shapes;

A'hh you are pushing stack objects onto the vector.
    shapes.push_back(&amp;c2);

Maybe it should be a vector of reference wrapper to Shape std::vector&lt;std::reference_wrapper&lt;Shape&gt;&gt;.
Getting a circle from a shape.
    c3 = *shapes[0];

Not sure that should really happen. The interface to Shape should be how you manipulate the object. Needing to convert the object to a circle seems unnecessary in most situations (you should probably have virtual functions that do the actions you need). Sometimes things have unique actions then you need to convert them back.But in these situations just use dynamic_cast directly (this also shows you are doing the conversion very explicitly).
Based on comments below:

I will need to pull name's and description's to display to the user

Its easier to ask the object to display itself rather the pull details about the object and then display them.
The simplist example is just printing information to a stream:
// Original Way
Circle    c(5);
std::cout &lt;&lt; &quot;Circle: &quot;  &lt;&lt; c.getName() 
          &lt;&lt; &quot; Edges: &quot;  &lt;&lt; c. getEdges 
          &lt;&lt; &quot; Radius: &quot; &lt;&lt; c.getRadius()
          &lt;&lt; &quot;\n&quot;;

// What I would do is make the serialization of the object to a stream
// a member method that does the work.

class Shape
{
    virtual void print(std::ostream&amp; stream) const = 0; // Can print a Shape
                                                  // Must be specialized for 
                                                  // Specific types.

    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; stream, Shape const&amp; shape)
    {
        shape.print(stream);
        return stream;
    }
};

// Now you print like this:
Circle    c(5);
std::cout &lt;&lt; c &lt;&lt; &quot;\n&quot;;

You don't need to expose the members just because you need serialization. Doing it this ways adds consistency so that all objects of a particular type are serialized in the same way. If you need to change what it looks like you have a single place in the code that needs modifying.
We can extend the above to other graphical representations.
struct DisplayInterface
{
     // This is an interface for drawing shapes on a display.
     // You can imagine it has the standard drawing functions.
     // But imagine a base set.
     void drawLine(Pt const&amp; tr, Pt const&amp; bl);
     void drawCircle(Pt const&amp; tr center, unsigned int radius);
     void drawPolygon(std::vector&lt;Pt&gt; const&amp; pts);
     void drawText(Pt const&amp; bl, unsigned int fontSize, std::string const&amp; str);
};

// Now in your drawing code you pass the DisplayInterface to the object
// So it can draw itself. So usually the drawing system provides an
// interface that all drawable objects need to implement.

struct Drawable
{
    virtual void display(DisplayInterface&amp; di) = 0;
};

class Shape: public Drawable  // All shapes are drawable
{                             // But each shape must implement
                              // Its own display()
};

class Circle: public Shape
{
     virtual void display(DisplayInterface&amp; di)
     {
          di.drawCircle(Pt(0,0), radius);
          di.drawText(Pt(0,15), 12, name);
     }
};