C++ 抽象类的好处是什么

C++ 抽象类的好处是什么,c++,abstract-class,C++,Abstract Class,举个例子, class base{ public: virtual void abstract() = 0; }; class derived:public base{ public: void abstract(){cout << "Abstract\n";} }; int main{ derived d; d.abstract(); return 0; } 类基{ 公众: 虚空抽象()=0; }; 派生类:公共基{ 公众: void abstract(){cout抽象类用于

举个例子,

class base{
public:
virtual void abstract() = 0;
};

class derived:public base{
public:
void abstract(){cout << "Abstract\n";}
};

int main{
derived d;
d.abstract();
return 0;
}
类基{
公众:
虚空抽象()=0;
};
派生类:公共基{
公众:

void abstract(){cout抽象类用于为某些功能提供接口,其中确切的行为由调用方的类定义。为了确保函数的“用户”实现其功能,您可以在基类中使用抽象函数。这样,如果“用户”没有提供所需的函数之一,代码无法编译。

正如您所注意到的,在示例代码中,没有必要使用单独的基类和派生类

通常,具有虚拟函数的类的用途是动态多态性,但您的代码没有使用它

假设您有一些代码使用了
base*
,而不知道它实际指向(几个)派生类中的哪一个。假设它们各自有
abstract()的不同实现
。假设您想强制编写
base
派生类的任何人实现自己版本的
abstract()
。那么有理由将
abstract()
设为纯虚拟函数,从而有理由将
base
设为抽象类:

#include <iostream>
#include <cstdlib>
#include <ctime>

struct Base {
    virtual void abstract() = 0;
    virtual ~Base() {};
};

struct Derived1 : Base {
    void abstract() { std::cout << "Derived1\n"; }
};

struct Derived2 : Base {
    void abstract() { std::cout << "Derived2\n"; }
};

Base *random_object() {
    if (std::rand() < RAND_MAX/2) {
        return new Derived1();
    } else {
        return new Derived2();
    }
}

int main() {
    std::srand(std::time(0));
    Base *b = random_object();
    b->abstract();
    delete b;
}
#包括
#包括
#包括
结构基{
虚空抽象()=0;
虚~Base(){};
};
结构Derived1:Base{

void abstract(){std::cout一个
抽象(基)类的目的是为子类定义一个
接口
。通过这种方式,你可以确定你的类必须能够做什么(它的方法),而不是它如何做事情(实现)。
当您从
抽象类派生时,您承诺在子类中提供特定行为。使用此方法,函数可以使用您的对象并执行其操作,而无需详细了解其特定行为。
到处都有类层次结构,如
.NET
-framework中的类层次结构,用于表示诸如UI控件之类的概念或事物。
第二,有一个类的实例有时是没有意义的。考虑一个类<代码>动物< /代码>。<代码>动物< /代码>是如何定义的?实例化一个<代码>动物< /代码>是没有意义的,而是一个<代码>狗< /代码>或一个<代码>猫>代码>,源于<代码>动物。< /代码>

在“抽象”字,抽象类中。(完全抽象时也称为接口)从一组类似类的实现中抽象出来。在这里,相似意味着它们具有相同的函数集,但可能以不同的方式实现它们

抽象类本身并不定义实现。在程序中传递(指向的指针或引用)抽象类只传递一个“封闭包”,您可以与之交互(例如抖动)。但您隐藏了包内的内容,包括接口的实现方式(例如抖动时发生的情况)

也就是说,抽象类只是将抽象提高了一个级别。类描述对象具有的属性和行为,而抽象类只描述您可以对对象执行的操作。只有实际的实现定义了行为

尽管如此,一个重要的事实是您不能创建抽象类的实例


在设计一个软件时,抽象类/接口是一种非常重要的抽象方法。当软件的某个部分想要与它不知道的东西进行交互时,您可以编写一个接口来描述这样一个对象必须提供的功能,而不必指定实际的类型。这使得可以轻松地传递不同类型的对象。使用指向此类接口/抽象类的指针/引用的函数可以在不知道其实际类型的情况下与对象交互。

下面是一个示例:假设您的程序需要计算不同形状的面积

class shape{
public:
    virtual double area() = 0;
};

class triangle:public shape{
public:
    triangle(double base, double height) : b(base), h(height) {}
    double area(){ return 0.5 * b * h; }
private:
    double b;
    double h;
};

class circle:public shape{
public:
    circle(double radius) : r(radius) {}
    double area(){ return M_PI * r * r; }
private:
    double r;
};

int main{
    std::vector<shape*> shapes;

    //add whatever shapes you want here
    shapes.push_back( new triangle(4, 5) );
    shapes.push_back( new circle(3) );

    double dTotal = 0.0;
    std::vector<shape*>::iterator i;
    for (i = shapes.begin(); i != shapes.end(); i++)
    {
        dTotal += (*i)->area();
        delete *i;
    }

    cout << dTotal;
    return 0;
}
类形状{
公众:
虚拟双区()=0;
};
类三角形:公共形状{
公众:
三角形(双基,双高):b(基),h(高){}
双区域(){返回0.5*b*h;}
私人:
双b;
双h;
};
班级圈子:公共形态{
公众:
圆(双半径):r(半径){}
双区域(){return M_PI*r*r;}
私人:
双r;
};
int main{
向量形状;
//在这里添加您想要的任何形状
形状。推回(新三角形(4,5));
形状。推回(新圆圈(3));
双D总=0.0;
std::vector::迭代器i;
对于(i=shapes.begin();i!=shapes.end();i++)
{
dTotal+=(*i)->area();
删除*i;
}

cout在不希望创建类的对象的情况下,抽象类也很有用

想想这个,

/* Abstract Class Animal */
class Animal
{
public:
    virtual void eat() = 0;
    virtual void walk() = 0;
};

class Dog:public Animal
{
public:
    void walk() { std::cout<<"\nWalk with Paws"; }   
    void eat()  { std::cout<<"\nEat meat";       }
};

class Horse:public Animal
{
public:
        void walk() {  std::cout<<"\nWalk with Hooves"; }   
        void eat()  {  std::cout<<"\nEat Grass";        }
};

int main()
{
    Dog d;
    Horse h;

    d.eat();
    d.walk();
    h.eat();
    h.walk();
return 0;
}
/*抽象类动物*/
类动物
{
公众:
虚空eat()=0;
虚空行走()=0;
};
犬类:公共动物
{
公众:

void walk(){std::coutSteve Jessop已经指出了为什么需要抽象类和虚拟函数。 您可以强制使用vtable来实现动态调度

抽象基类声明派生类的公共特性。 虚函数确保在编译时无法确定对象的类型时调用正确的函数

在下面的示例中,
类其他
在编译时不知道提供了
类形状
的哪个派生。 唯一已知的是:每个
shape
派生将为
center
方法提供一个实现,因为它是纯
virtual
(否则程序不会编译和链接) 这足以提供功能。 程序将在运行时确定
shPtr
的类型,并调用正确的
center()

完全正确(表示调用了正确的中心函数)

-编辑
/* Abstract Class Animal */
class Animal
{
public:
    virtual void eat() = 0;
    virtual void walk() = 0;
};

class Dog:public Animal
{
public:
    void walk() { std::cout<<"\nWalk with Paws"; }   
    void eat()  { std::cout<<"\nEat meat";       }
};

class Horse:public Animal
{
public:
        void walk() {  std::cout<<"\nWalk with Hooves"; }   
        void eat()  {  std::cout<<"\nEat Grass";        }
};

int main()
{
    Dog d;
    Horse h;

    d.eat();
    d.walk();
    h.eat();
    h.walk();
return 0;
}
#include <string>
#include <iostream>

using namespace std;

class v2d
{
public: 
  double x, y;
  v2d (void) : x(0.0), y(0.0) { }
  v2d (double const a, double const b) : x(a), y(b) { }
};


class shape
{
public:
  string name;
  shape (void) : name() { }
  shape (string const n) : name(n) { }
  virtual v2d center (void) const = 0;
};


class circle : public shape 
{
private:
  v2d center_point;
  double radius;
public:
  circle (void) : shape("Circle"), center_point(), radius(0.0) { }
  circle (v2d const cp, double const r) : shape("Circle"), center_point(cp), radius(r) { }
  v2d center (void) const { return center_point; }
};

class square : public shape
{
private:
  v2d lowright;
  double sidelength;
public:
  square (void) : shape("Square"), lowright(), sidelength(0.0) { }
  square (v2d const tl, double const sl) : shape("Square"), lowright(tl), sidelength(sl) { }
  v2d center (void) const
  {
    double const halflen = sidelength/2.0;
    return v2d(lowright.x+halflen, lowright.y+halflen);
  }
};


class other
{
private:
  shape *shPtr;
public:
  other (void) : shPtr(NULL) { }
  other (shape *sh_ptr) : shPtr(sh_ptr) { }
  void doSomething (void)
  {
    cout << "Center of this Shape, which is a " << shPtr->name << " is: "<< shPtr->center().x << ", " << shPtr->center().y << endl;
  }
};



int main (void) 
{

  v2d sq_c(1.0, 2.0), circ_c(4.0, 4.0);
  square square_obj(sq_c, 5.0);
  circle circle_obj(circ_c, 2.0);

  other other1 (&square_obj), other2(&circle_obj);

  cout << fixed << setprecision(2);

  other1.doSomething();
  other2.doSomething();

  return 0;
}
Center of this Shape, which is a Square is: 3.50, 4.50
Center of this Shape, which is a Circle is: 4.00, 4.00
#include <string>
#include <iostream>
#include <vector>

using namespace std;

class Animal
{
public:
  virtual string food() = 0;
  virtual string name() = 0; 
  void eat()  { cout << "A " << name() << " is eating " << food() << endl; }
};

class Dog:public Animal
{
public:
  string name() { return "Dog"; }
  string food() { return "Meat"; }
};

class Horse:public Animal
{
public:
  string name() { return "Horse"; }
  string food() { return "Gras"; }
};

void feed_all_animals (vector<Animal*> animals)
{
  for (size_t i=0; i<animals.size(); ++i)
  {
    cout << "Feeding animal " << i+1 << " (a " << animals[i]->name() << ") with " << animals[i]->food() << endl;
    animals[i]->eat();
  }
}

int main (void)
{
  vector<Animal*> animals;
  // We have a zoo with three dogs and two horses
  Dog dog1, dog2, dog3;
  Horse horse1, horse2;
  animals.push_back((Animal*)&dog1);
  animals.push_back((Animal*)&dog2);
  animals.push_back((Animal*)&dog3);
  animals.push_back((Animal*)&horse1);
  animals.push_back((Animal*)&horse2);
  // now we let the user add another animal
  int ani(0);
  cout << "Do you want to add a Horse [1] or a Dog [0]: ";
  cin >> ani;
  switch (ani)
  {
    case 1: animals.push_back((Animal*)new Horse); break;
    default: animals.push_back((Animal*)new Dog); break;
  }
  // so they don't starve
  feed_all_animals(animals);

  delete animals[animals.size()-1];
  animals.clear();
  return 0;
}