I am new at C++, and have some problems with it. I would like to create an abstract class, and two more abstract classes that inherit from that class. Finally, those two classes are used to be implemented by concrete classes. Here are my header and source files:
/*
* Cylinder.h
*/
#ifndef CYLINDER_H_
#define CYLINDER_H_
class Shape{
public:
virtual ~Shape();
virtual const double area()=0;
virtual const void printDetails();
};
class Shape2D: virtual public Shape{
public:
virtual const double scope()=0;
};
class Shape3D: virtual public Shape{
public:
virtual const double volume()=0;
};
class Rectangle: public Shape2D{
private:
double a;
double H;
public:
Rectangle();
Rectangle(double a, double H);
Rectangle(Rectangle &r);
double getA() const;
double getH() const;
void setA(double a);
void setH(double H);
};
class Circle: public Shape2D{
private:
double r;
public:
Circle();
Circle(double r);
Circle(Circle &c);
double getR() const;
void setR(double r);
};
class Cylinder: public Shape3D{
private:
Circle base;
Rectangle wrapper;
public:
Cylinder();
Cylinder(Rectangle &r, Circle &c);
Cylinder(double a, double H, double r);
Cylinder(Cylinder &c);
double getHeight() const;
double getBaseRadius() const;
double getBaseArea() const;
double getBaseScope() const;
double getWrapperArea() const;
double getWrapperScope() const;
void setHeight(double H);
void setRadius(double r);
Rectangle* getWrapper() const;
Circle* getBase() const;
};
#endif /* CYLINDER_H_ */
/*
* Cylinder.cpp
*/
#include <iostream>
#include "Cylinder.h"
#include <math.h>
using namespace std;
void Shape2D::printDetails() const{
cout<<"\nArea: "<<area();
cout<<"\nScope: "<<scope();
}
void Shape3D::printDetails() const{
cout<<"\nArea: "<<area();
cout<<"\nVolume: "<<volume();
}
Rectangle::Rectangle(){
H=0.0;
a=0.0;
}
Rectangle::Rectangle(double a, double H){
this->H=H;
this->a=a;
}
Rectangle::Rectangle(Rectangle &r){
a=r.a;
H=r.H;
}
Rectangle::~Rectangle(){
cout<<"Rectangle deallocated.";
}
double Rectangle::getA() const{
return a;
}
double Rectangle::getH() const{
return H;
}
void Rectangle::setA(double a){
this->a=a;
}
void Rectangle::setH(double H){
this->H=H;
}
double Rectangle::scope() const{
return 2*a+2*H;
}
double Rectangle::area() const{
return a*H;
}
void Rectangle::printDetails() const{
cout<<"\nDimensions of rectangle: "<<a<<"*"<<H;
Shape::printDetails();
}
Circle::Circle(){
r=0.0;
}
Circle::Circle(double r){
this->r=r;
}
Circle::Circle(Circle &c){
r=c.r;
}
Circle::~Circle(){
cout<<"Circle deallocated.";
}
double Circle::getR() const{
return r;
}
void Circle::setR(double r){
this->r=r;
}
double Circle::scope() const{
return 2*r*M_PI;
}
double Circle::area() const{
return r*r*M_PI;
}
void Circle::printDetails() const{
cout<<"\nRadius of circle: "<<r;
Shape::printDetails();
}
Cylinder::Cylinder(){
wrapper=new Rectangle(0.0,0.0);
base=new Circle(0.0);
}
Cylinder::Cylinder(Rectangle &r, Circle &c){
base=c;
wrapper=r;
}
Cylinder::Cylinder(double a=0.0, double H=0.0, double r=0.0){
wrapper=new Rectangle(a,H);
base=new Circle(r);
}
Cylinder::Cylinder(Cylinder &c){
c.base=new Circle(c.base);
c.wrapper=new Rectangle(c.wrapper);
}
Cylinder::~Cylinder(){
delete base;
delete wrapper;
}
double Cylinder::getHeight() const{
return wrapper.getH();
}
double Cylinder::getBaseRadius() const{
return base.getR();
}
double Cylinder::getBaseArea() const{
return base.area();
}
double Cylinder::getBaseScope() const{
return base.scope();
}
double Cylinder::getWrapperArea() const{
return wrapper.area();
}
double Cylinder::getWrapperScope() const{
return wrapper.scope();
}
void Cylinder::setHeight(double H){
wrapper.setH(H);
}
void Cylinder::setRadius(double r){
base.setR(r);
wrapper.setA(2*base.getR()*M_PI);
}
double Cylinder::volume() const{
return base*wrapper.getH();
}
double Cylinder::area() const{
return 2*base.area+wrapper.area;
}
void Cylinder::printDetails() const{
cout<<"\nRadius of base of Cilynder: "<<base.getR();
cout<<"\nHeight of wrapper: "<<wrapper.getH();
Shape::printDetails();
}
Rectangle* Cylinder::getWrapper() const{
return new Rectangle(wrapper);
}
Circle* Cylinder::getBase() const{
return new Circle(base);
}
My compiler gives me different errors as I try to modify the code to accomplish somehow to have classes Rectangle, Circle and Cylinder as non abstract ones. I am not sure where should I put method definitions (should they be duplicated in inherited classes), and what is their proper form actually. Sorry for long text. I hope someone can help me. Thanks in advance
Sam
You aren't implementing the pure virtual methods. Whenever you have pure virtual methods (virtual void whatever()=0), that makes the class abstract. Abstract classes can not be instantiated. In order to be instantiated, concrete subclasses must implement all the pure virtual methods from ancestor classes.
For example, Rectangle is missing the scope method inherited from Shape2D, and the area method inherited from Shape. That will cause errors along the lines of "can't instantiate Rectangle class because it is abstract." It looks like you have the implementations of those methods lower in the file, but they aren't declared anywhere inside the Rectangle class.
Related
How to properly use a class object (Point) inside my class (Segment) object that they both inheritoring from the class(Figure2D)?
The Figure.h file:
#include <math.h>
#include <ostream>
class Figure2D
{
private:
double x;
double y;
double length;
double height;
char* name = NULL;
public:
Figure2D(double l, double h, double x = 0, double y = 0);
Figure2D(Figure2D& f);
Figure2D();
virtual ~Figure2D();
const Figure2D& operator=(Figure2D& d);
void setName(const char*);
double getX()const;
double getY()const;
double getLength()const;
double getHeight()const;
const char* getName()const;
double Area()const;
double Perimeter()const;
void Shift(double dx, double dy);
void MoveTo(double newX, double newY);
void Resize(double newL, double newH);
void Scale(double Kx, double Ky);
bool isInside(Figure2D* P);//Point(P->getX(),P->getT()) lies inside the figure
void print()const;
friend std::ostream& operator<<(std::ostream& o, Figure2D& d);
};
The Point.h file:
#pragma once
#include "Figure2D.h"
class Point : public Figure2D {
public:
Point(const char* s,int x,int y) :Figure2D(0,0,x,y)
{
setName(s);
}
Point(){}
Point(const Point& other)
{
}
~Point() {}
};
The Segment.h file:
#pragma once
#include "Figure2D.h"
#include "Point.h"
class Segment : public Figure2D
{
public:
Segment(const char* s, Point& p1, Point& p2)
{
setName(s);
if (p1.getX() <= p2.getX() && p1.getY() <= p2.getY())
{
isLeftToRightSegment = true;
}
else
{
isLeftToRightSegment = false;
}
}
protected:
bool isLeftToRightSegment;
};
I cant make this code in the main.cpp properly:
Segment S("Segment PQ", P, Q);
Eventually i want to make shaps as(Point,Segment,Rectangle,Square,Circle) with the
Figure2D class
I am writing a program that has different shape classes
There is a base shape class similar to the following:
class Shape
{
public:
Shape(int x, int y, int size, COLORREF colorRef);
~Shape();
bool operator == (const Shape&) const;
int x() const;
int y() const;
int size() const;
protected:
int xCoord;
int yCoord;
int shapeSize;
COLORREF color;
};
And then some derived classes similar to the following:
class Circle : public Shape
{
public:
Circle(int x, int y, int size, COLORREF colorRef) : Shape(x, y, size, colorRef)
{
this->radius = (double)shapeSize / 2;
this->xCenter = (double)xCoord + radius;
this->yCenter = (double)yCoord - radius;
}
~Circle() {}
private:
double radius;
double xCenter;
double yCenter;
};
class Square : public Shape
{
public:
Square(int x, int y, int size, COLORREF colorRef) : Shape(x, y, size, colorRef) {}
~Square() {}
};
class Triangle : public Shape
{
public:
Triangle(int x, int y, int size, COLORREF colorRef) : Shape(x, y, size, colorRef) {}
~Triangle() {}
};
I would like to overload the == operator in the shape class so that I can determine if 2 shapes are identical. If I could assume both shapes being compared were of the same class then I know it would be fairly straight forward, but how do I go about testing whether 2 objects of the different derived classes are equal? For example, how do I determine that Triangle t != Circle c?
You have to determine which function to call based on type of two objects. This pattern in C++ is called double-dispatch (or Visitor pattern).
The most common implementation assumes that all derived classes (shapes in your example) are known - so you can list them in base class:
class Circle;
class Rectangle;
// all shapes here
class Shape {
public:
virtual ~Shape() = default; // good habit is to add virtual destructor to all polymorphic classes (those with virtual methods)
bool operator == (const Shape& other) const {
return equalTo(other);
}
virtual bool equalTo(const Shape& other) const = 0;
virtual bool doEqualTo(const Circle& other) const { return false; }
virtual bool doEqualTo(const Rectangle& other) const { return false; }
// etc.. for all other shapes
};
class Circle : public Shape {
// ...
protected:
virtual bool equalTo(const Shape& other) const
{
return other.doEqualTo(*this); // call doEqualTo(Circle) - first virtual dispatch
}
virtual bool doEqualTo(const Circle& other) const
{
return other.center == center && other.radius == radius; // second virtual dispatch
}
};
As you can see - to perform action - you have to call 2 virtual functions (so double-dispatch)
Ok, here's an idea for using the curious recurring template pattern to make implementing derived classes easier while allowing the == operator to work as expected. This maybe overkill, but it should work for your scenario.
Start by filling out your base Shape class. Added to your basic definition is an implementation of operator== that invokes a helper called CompareTypesAndDimensions. The function calls into two virtual methods, TypeCompare and Compare.
class Shape
{
public:
Shape(int x, int y, int size, COLORREF colorRef) : xCoord(x), yCoord(y), shapeSize(size), color(colorRef) {}
virtual ~Shape() {}; // need at least one virtual member for dynamic_cast
int x() const { return xCoord; }
int y() const { return yCoord; }
int size() const { return shapeSize; }
COLORREF col() const { return color; };
bool operator == (const Shape& other) const
{
return CompareTypesAndDimensions(other);
}
bool BaseShapeCompare(const Shape& other) const
{
return ((other.xCoord == xCoord) && (other.yCoord == yCoord) && (other.shapeSize == shapeSize) && (other.color == color));
}
virtual bool TypeCompare(const Shape& other) const = 0;
virtual bool Compare(const Shape& other) const = 0;
bool CompareTypesAndDimensions(const Shape& other) const
{
// make sure the types checks are reciprocals
// we don't accidently compare a "Square" with a "Rectangle" if they inherit from each other
if (TypeCompare(other))
{
return Compare(other);
}
return false;
}
protected:
int xCoord;
int yCoord;
int shapeSize;
COLORREF color;
};
The idea being with the above is that Circle, Triangle, and Square could just implement their own version of TypeCompare and Compare and be done with it. But wait! What if we could save some typing by having a template base class do some work for us - especially for validating that both compared instances are of the same type. And not having to a stock Compare function for the simpler types such as Square and Triangle.
Let's introduce a template class that inherits from Shape. This class, ShapeComparable provides the implementations for Compare and TypeCompare. The only thing it needs the concrete class below it to deal with is a method to handle comparing its own methods.
template <typename T>
class ShapeComparable : public Shape
{
public:
ShapeComparable(int x, int y, int size, COLORREF colorRef) : Shape(x, y,size,colorRef)
{}
bool TypeCompare(const Shape& other) const override
{
auto pOtherCastToDerived = dynamic_cast<const T*>(&other);
return (pOtherCastToDerived != nullptr);
}
bool Compare(const Shape& other) const override
{
if (BaseShapeCompare(other))
{
auto pOtherCastToDerived = dynamic_cast<const T*>(&other);
if (pOtherCastToDerived)
{
return this->CompareDerived(*pOtherCastToDerived);
}
}
return false;
}
// derived classes that don't have members to compare will just inherit this member
virtual bool CompareDerived(const T& other) const
{
return true;
}
};
The magic with the above is that TypeCompare utilizes a dynamic_cast to validate if the two instances being compared are of the same type. If you try to compare a Triangle to a Circle, the dynamic cast fails. Hence, operator== will return false.
Now let's see what the rest of the classes look like. Start with Circle, it inherits from ShapeComparable and provides an implementation for CompareDerived.
class Circle : public ShapeComparable<Circle>
{
public:
Circle(int x, int y, int size, COLORREF colorRef) : ShapeComparable(x,y,size,colorRef)
{
this->radius = (double)shapeSize / 2;
this->xCenter = (double)xCoord + radius;
this->yCenter = (double)yCoord - radius;
}
bool CompareDerived(const Circle& other) const
{
// BaseCompare has already been invoked by the time this method is invoked.
return ((other.radius == radius) && (other.xCenter == xCenter) && (other.yCenter == yCenter));
}
private:
double radius;
double xCenter;
double yCenter;
};
But Triangle and Square are as simple as it gets.
class Triangle : public ShapeComparable<Triangle>
{
public:
Triangle(int x, int y, int size, COLORREF colorRef) : ShapeComparable(x, y, size, colorRef) {}
};
class Square : public ShapeComparable<Square>
{
Square(int x, int y, int size, COLORREF colorRef) : ShapeComparable(x, y, size, colorRef) {}
};
And if you ever need to introduce a new property to Triangle and Square, you just need to provide a CompareDerived method.
The above works with the assumption is that you wouldn't have additional shapes derived from another concrete shape class. Otherwise, the CompareType function won't be reciprocal when comparing a Square to a Rhombus.
I would like to check wether my 2d point and 3d points are identical using operator== that returns true if they are.
How can I implement that?
Do I need to add overloaded operator into both classes or what?
How to compare 2 arguments x and y?
My code:
#include <iostream>
using namespace std;
class Point2D {
public:
Point2D();
// ~Point2D();
void SetX(double x);
void SetY(double y);
double GetX();
double GetY();
protected:
double m_x, m_y;
};
class Point3D :Point2D {
public:
Point3D() :Point2D() { m_z = 0.0; };
protected:
double m_z;
};
Point2D::Point2D() {
m_x = 0.0;
m_y = 0.0;
}
void Point2D::SetX(double x) {
m_x = x;
}
void Point2D::SetY(double y) {
m_y = y;
}
double Point2D::GetX() {
return m_x;
}
double Point2D::GetY() {
return m_y;
}
int main() {
Point2D T;
cout << T.GetX() << " " << T.GetX() << endl;
return 0;
}
First, you probably want public inheritance:
class Point3D : public Point2D {
// ~~~~~~~~~~~~~^
Once you have that, you can rely on polymorphism to handle things for you and only implement comparison operator for Point2D:
// the arguments should be const, but your classes are not const correct
bool operator== (/*const*/ Point2D& lhs, /*const*/ Point2D& rhs)
{
return lhs.GetX() == rhs.GetX() && lhs.GetY() == rhs.GetY();
}
int main() {
Point2D p2;
Point3D p3;
std::cout << std::boolalpha << (p2 == p3);
}
You can further improve it by making your functions const:
class Point2D {
public:
Point2D();
void SetX(double x);
void SetY(double y);
double GetX() const; //here
double GetY() const; //here
protected:
double m_x, m_y;
};
double Point2D::GetX() const { //and here
return m_x;
}
double Point2D::GetY() const { //and here
return m_y;
}
//now you can pass arguments by const reference, no accidental modifications in the operator
bool operator== (const Point2D& lhs, const Point2D& rhs)
{
return lhs.GetX() == rhs.GetX() && lhs.GetY() == rhs.GetY();
}
I have the following classes:
EuropeanOption.h
#pragma once
class OptionPricer;
class EuropeanOption
{
protected:
double dividend;
double strike;
double vol;
double maturity;
double spot;
public:
EuropeanOption(void);
virtual ~EuropeanOption(void);
virtual double price(double rate, const OptionPricer& optionPricer) const = 0;
virtual short getSign() const =0;
double getDividend() const;
double getStrike() const;
double getVol () const;
double getMaturity() const;
double getSpot() const;
void setDividend(double dividend_);
void setStrike(double strike_);
void setVol(double vol_);
void setMaturity(double maturity_);
void setSpot(double spot_);
};
EuropeanOption.cpp
#include "OptionPricer.h"
#include "EuropeanOption.h"
EuropeanOption::EuropeanOption(void)
{
}
EuropeanOption::~EuropeanOption(void)
{
}
double EuropeanOption::getDividend() const
{
return dividend;
}
double EuropeanOption::getMaturity() const
{
return maturity;
}
double EuropeanOption::getStrike() const
{
return strike;
}
double EuropeanOption::getSpot() const
{
return spot;
}
double EuropeanOption::getVol() const
{
return vol;
}
void EuropeanOption::setDividend(double dividend_)
{
dividend = dividend_;
}
void EuropeanOption::setMaturity(double maturity_)
{
maturity = maturity_;
}
void EuropeanOption::setSpot(double spot_)
{
spot = spot_;
}
void EuropeanOption::setVol(double vol_)
{
vol = vol_;
}
void EuropeanOption::setStrike(double strike_)
{
strike = strike_;
}
EuropeanCall.h
#pragma once
#include "EuropeanOption.h"
class EuropeanCall :
public EuropeanOption
{
public:
EuropeanCall(void);
EuropeanCall(double spot_, double strike_, double maturity_, double vol_, double dividend_ = 0);
~EuropeanCall(void);
short getSign() const;
double price(const OptionPricer& optionPricer, double rate) const;
}
;
EuropeanCall.cpp
#include "EuropeanCall.h"
#include "OptionPricer.h"
#include <cstdlib>
EuropeanCall::EuropeanCall(void)
{
}
EuropeanCall::EuropeanCall(double spot_, double strike_, double maturity_, double vol_, double dividend_)
{
spot = spot_;
strike = strike_;
maturity = maturity_;
vol = vol_;
dividend = dividend_;
}
EuropeanCall::~EuropeanCall(void)
{
}
short EuropeanCall::getSign() const
{
return 1;
}
double EuropeanCall::price(const OptionPricer& optionPricer, double rate) const
{
return optionPricer.computePrice(*this, rate);
}
OptionPricer.h
#pragma once
#include "EuropeanOption.h"
class OptionPricer
{
public:
OptionPricer(void);
virtual double computePrice(const EuropeanOption& option, double rate) const =0;
virtual ~OptionPricer(void);
};
OptionPricer.cpp
#include "OptionPricer.h"
OptionPricer::OptionPricer(void)
{
}
OptionPricer::~OptionPricer(void)
{
}
In my main function, when trying to instanciate an EuropeanCall like this:
EuropeanCall myCall(spot,strike,maturity,vol);
I get this error message:
object of abstract class type "EuropeanCall" is not allowed
I don't understand why the compiler considers EuropeanCall as an abstract class. Some help please?
You declared:
virtual double price(double rate, const OptionPricer& optionPricer) const = 0;
in your base class but got the parameters the wrong way round in your derived class:
double price(const OptionPricer& optionPricer, double rate) const;
This is not considered an override.
If some member function vf is declared as virtual in a class Base, and
some class Derived, which is derived, directly or indirectly, from
Base, has a declaration for member function with the same
name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers
Then this function in the class Derived is also virtual (whether or
not the keyword virtual is used in its declaration) and overrides
Base::vf (whether or not the word override is used in its
declaration).
Since C++11 you can use the override specifier to ensure that a function is indeed virtual and is overriding a virtual function from the base class.
struct A
{
virtual void foo();
void bar();
};
struct B : A
{
void foo() const override; // Error: B::foo does not override A::foo
// (signature mismatch)
void foo() override; // OK: B::foo overrides A::foo
void bar() override; // Error: A::bar is not virtual
};
The function
virtual double price(double rate, const OptionPricer& optionPricer) const = 0;
Is pure virtual function, thus the classes are abstract. You cannot instantiate on instance of a class with a pure virtual function.
Your attempted override does not match this function signature;
double price(const OptionPricer& optionPricer, double rate) const;
The order of the parameters matter. To catch issues such as this, you can use the override specifier and the compiler will check that the function is overriding.
double price(const OptionPricer& optionPricer, double rate) const override;
// The override above will cause a compiler error.
I'm trying to create a .dll file. I define an class
class Contactmodel
public:
Contactmodel();
virtual ~Contactmodel();
Then, I try to create an instance of this class
virtual Contactmodel *clone() const {return new Contactmodel();}
But when I compile, it causes the error: object of abstract class type is not allowed when create an instance of a abstract class
Could you please show me what I did wrong to create an instance and how to fix it? thank you!
My header file
#pragma once
// contactmodelCohesive.h
#include "contactmodel/src/contactmodelmechanical.h"
#ifdef Cohesive_LIB
# define Cohesive_EXPORT EXPORT_TAG
#elif defined(NO_MODEL_IMPORT)
# define Cohesive_EXPORT
#else
# define Cohesive_EXPORT IMPORT_TAG
#endif
namespace cmodelsxd {
using namespace itasca;
class ContactModelCohesive : public ContactModelMechanical {
public:
Cohesive_EXPORT ContactModelCohesive();
Cohesive_EXPORT virtual ~ContactModelCohesive();
virtual void copy(const ContactModel *c);
virtual void archive(ArchiveStream &);
virtual QString getName() const { return "Cohesive"; }
virtual void setIndex(int i) { index_=i;}
virtual int getIndex() const {return index_;}
enum PropertyKeys {
kwKn=1
, kwKs
, kwFric
, kwForce
, kwMoment
, kwState
, kwRGap
, kwConRad
, kwSig
, kwTau
, kwEmod
, kwKRatio
, kwTenStrength
, kwCoh
, kwPhiF
, kwPhiD
, kwInelasDeform
, kwDamagevar
, kwAlpha
, kwLamda
, kwwsig
, kwwcoh
};
virtual QString getProperties() const {
return " kn"
",ks"
",fric"
",coh_force"
",coh_moment"
",state"
",rgap"
",con_rad"
",sigma"
",tau"
",emod"
",kratio"
",ten_strength"
",cohesion"
",phi_f"
",phi_d"
",in_deform"
",D_var"
",alpha"
",lamda"
",w_sig"
",w_coh";
}
enum FishCallEvents { fActivated=0, fBondBreak };
virtual QString getFishCallEvents() const { return "contact_activated,contact_break"; }
virtual QVariant getProperty(uint i,const IContact *) const;
virtual bool getPropertyGlobal(uint i) const;
virtual bool setProperty(uint i,const QVariant &v,IContact *);
virtual bool getPropertyReadOnly(uint i) const;
enum MethodKeys { kwDeformability=1
, kwcohBond
, kwcohUnbond
};
virtual QString getMethods() const {
return "deformability"
",bond"
",unbond";
}
virtual QString getMethodArguments(uint i) const;
virtual bool setMethod(uint i,const QVector<QVariant> &vl,IContact *con=0); // Base 1 - returns true if timestep contributions need to be updated
virtual uint getMinorVersion() const;
virtual bool validate(ContactModelMechanicalState *state,const double ×tep);
//virtual bool endPropertyUpdated(const QString &name,const IContactMechanical *c);
virtual bool forceDisplacementLaw(ContactModelMechanicalState *state,const double ×tep);
virtual DVect2 getEffectiveTranslationalStiffness() const { DVect2 ret = effectiveTranslationalStiffness_; return ret;}
virtual DAVect getEffectiveRotationalStiffness() const {if (!cohProps_) return DAVect(0.0); return cohProps_->coh_AngStiff_;}
virtual ContactModelCohesive *clone() const { return NEWC(ContactModelCohesive()); }
virtual double getActivityDistance() const {return rgap_;}
virtual bool isOKToDelete() const { return !isBonded(); }
virtual void resetForcesAndMoments() { cohF(DVect(0.0)); cohM(DAVect(0.0));}
virtual bool checkActivity(const double &gap) { return (gap <= rgap_ || isBonded()); }
virtual bool isBonded() const { return cohProps_ ? (cohProps_->coh_state_==3) : false; }
bool hasPBond() const {return cohProps_ ? true:false;}
const double & rgap() const {return rgap_;}
void rgap(const double &d) {rgap_=d;}
int cohState() const {return hasPBond() ? cohProps_->coh_state_: 0;}
void cohState(int i) { if(!hasPBond()) return; cohProps_->coh_state_=i;}
double cohKn() const {return (hasPBond() ? (cohProps_->coh_kn_) : 0.0);}
void cohKn(const double &d) { if(!hasPBond()) return; cohProps_->coh_kn_=d;}
double cohKs() const {return (hasPBond() ? (cohProps_->coh_ks_) : 0.0);}
void cohKs(const double &d) { if(!hasPBond()) return; cohProps_->coh_ks_=d;}
double cohFric() const {return (hasPBond() ? (cohProps_->coh_fric_) : 0.0);}
void cohFric(const double &d) { if(!hasPBond()) return; cohProps_->coh_fric_=d;}
double cohTen() const {return (hasPBond() ? (cohProps_->coh_ten_) : 0.0);}
void cohTen(const double &d) { if(!hasPBond()) return; cohProps_->coh_ten_=d;}
double cohLamda() const {return (hasPBond() ? (cohProps_->coh_lamda_) : 0.0);}
void cohLamda(const double &d) { if(!hasPBond()) return; cohProps_->coh_lamda_=d;}
double cohAlpha() const {return (hasPBond() ? (cohProps_->coh_alpha_) : 0.0);}
void cohAlpha(const double &d) { if(!hasPBond()) return; cohProps_->coh_alpha_=d;}
double cohInelas() const {return (hasPBond() ? (cohProps_->coh_inelas_) : 0.0);}
void cohInelas(const double &d) { if(!hasPBond()) return; cohProps_->coh_inelas_=d;}
double cohDvar() const {return (hasPBond() ? (cohProps_->coh_dvar_) : 0.0);}
void cohDvar(const double &d) { if(!hasPBond()) return; cohProps_->coh_dvar_=d;}
double cohCoh() const {return (hasPBond() ? (cohProps_->coh_coh_) : 0.0);}
void cohCoh(const double &d) { if(!hasPBond()) return; cohProps_->coh_coh_=d;}
double cohPhiD() const {return (hasPBond() ? (cohProps_->coh_phid_) : 0.0);}
void cohPhiD(const double &d) { if(!hasPBond()) return; cohProps_->coh_phid_=d;}
double cohPhiF() const {return (hasPBond() ? (cohProps_->coh_phif_) : 0.0);}
void cohPhiF(const double &d) { if(!hasPBond()) return; cohProps_->coh_phif_=d;}
double cohwsig() const {return (hasPBond() ? (cohProps_->w_sig) : 0.0);}
void cohwsig(const double &d) { if(!hasPBond()) return; cohProps_->w_sig=d;}
double cohwcoh() const {return (hasPBond() ? (cohProps_->w_coh) : 0.0);}
void cohwcoh(const double &d) { if(!hasPBond()) return; cohProps_->w_coh=d;}
DVect cohF() const {return hasPBond() ? cohProps_->coh_F_: DVect(0.0);}
void cohF(const DVect &f) { if(!hasPBond()) return; cohProps_->coh_F_=f;}
DAVect cohM() const {return hasPBond() ? cohProps_->coh_M_: DAVect(0.0);}
void cohM(const DAVect &m) { if(!hasPBond()) return; cohProps_->coh_M_=m;}
DVect2 cohTransStiff() const {return hasPBond() ? cohProps_->coh_TransStiff_: DVect2(0.0);}
void cohTransStiff(const DVect2 &f) { if(!hasPBond()) return; cohProps_->coh_TransStiff_=f;}
DAVect cohAngStiff() const {return hasPBond() ? cohProps_->coh_AngStiff_: DAVect(0.0);}
void cohAngStiff(const DAVect &m) { if(!hasPBond()) return; cohProps_->coh_AngStiff_=m;}
const DVect2 & effectiveTranslationalStiffness() const {return effectiveTranslationalStiffness_;}
void effectiveTranslationalStiffness(const DVect2 &v ) {effectiveTranslationalStiffness_=v;}
private:
static int index_;
struct cohProps {
cohProps() : coh_kn_(0.0), coh_ks_(0.0), coh_fric_(0.0), coh_state_(0), coh_ten_(0.0), coh_coh_(0.0),
coh_alpha_(1.0), coh_lamda_(0.0), coh_phid_(0.0), coh_phif_(0.0), coh_dvar_(0.0), coh_inelas_(0.0),
coh_F_(DVect(0.0)), coh_M_(DAVect(0.0)), coh_TransStiff_(0.0), coh_AngStiff_(0.0) {}
// parallel bond
int coh_state_; // Contact mode - 0 (NBNF), 1 (NBFT), 2 (NBFS), 3 (B)
double coh_kn_; // normal stiffness
double coh_ks_; // shear stiffness
double kn0;
double ks0;
double coh_fric_; // Moment contribution factor
double coh_ten_; // normal strength
double coh_coh_; // friction angle
double ten0;
double coh0;
double coh_inelas_; // friction angle
double coh_alpha_; // soften normal stiffness
double coh_lamda_; // soften normal stiffness
double coh_phid_; // soften normal stiffness
double phid0;
double coh_phif_; // soften normal stiffness
double coh_dvar_; // soften normal stiffness
DVect coh_F_; // Force in parallel bond
DAVect coh_M_; // moment in parallel bond
double mn;
double ms;
double w_sig;
double w_coh;
DVect2 coh_TransStiff_; // (Normal,Shear) Translational stiffness of the parallel bond
DAVect coh_AngStiff_; // (Normal,Shear) Rotational stiffness of the parallel bond
};
void updateEffectiveStiffness(ContactModelMechanicalState *state);
DVect3 cohData(const IContactMechanical *con) const; // Bond area and inertia
DVect2 cohSMax(const IContactMechanical *con) const; // Maximum stress (tensile,shear) at bond periphery
double cohShearStrength(const double &cohArea) const; // Bond shear strength
double rgap_; // reference gap for the linear part
cohProps * cohProps_; // The parallel bond properties
DVect2 effectiveTranslationalStiffness_;
}; //ContactModelCohesive
} // cmodelsxd
The reason for having abstract base classes is to provide an interface that concrete classes must implement. You are not supposed to create instances of the abstract base class.
Make clone() a pure virtual function and do not implement it in the base class. Implement it only in the concrete classes.
virtual Contactmodel *clone() const = 0;
You cannot create an instance of Contactmodel if Contactmodel is an abstract class (i.e. contains a pure virtual function). The clone is usually defined as a pure virtual function in a base class, the overloaded in the derived, like
struct IClonable
{
virtual IClonable* clone() const = 0;
virtual ~IClonable() = default;
};
class Foo: public IClonable
{
public:
Foo* clone() const override
{
return new Foo{*this};
}
};
int main()
{
Foo* foo = new Foo;
Foo* clone = foo->clone();
delete clone;
delete foo;
}
or, with smart pointers
#include <memory>
struct IClonable
{
virtual std::unique_ptr<IClonable> clone() const = 0;
virtual ~IClonable() = default;
};
class Foo: public IClonable
{
public:
std::unique_ptr<IClonable> clone() const override
{
return std::make_unique<Foo>(*this);
}
};
int main()
{
std::unique_ptr<IClonable> up_foo{new Foo};
std::unique_ptr<IClonable> up_clone = up_foo->clone();
}