c ++在类中获取/设置方法,我必须使用哪种数据类型?

时间:2015-06-09 09:55:03

标签: c++

我有一个类如下

class Circle{
   private:
    int radius;
    Circle* next
}

我会创建set / get方法......但我不知道我必须使用哪种数据类型。

int Circle::getRadius() const{return radius}
or 
int& Circle::getRadius() const{return radius}



void Circle::setRadius(int r) 
or 
void Circle::setRadius(int& r)  


CirCle* Circle::getNext() const{return next}
or 
Circle& Circle::getNext() const{return *(next)}



void Circle::setNext(Circle& circle)
{
    next = new Circle;
    next = circle;
 }
or 
void Circle::setRadius(Circle circle) 
{
    next = new Circle;
    next = circle;
}
or 
void Circle::setRadius(Circle* circle) 
{
    next = circle;
}

我非常喜欢Java。而Java参数都是参考。但是cpp是完全不同的,所以它让我发疯。谢谢你的帮助。

5 个答案:

答案 0 :(得分:3)

首先,我建议您阅读一些C ++教程。你的问题可能会在这里得到落实,因为看起来你真的没有尝试寻找问题的解决方案,而只是请求SO寻求帮助。

需要了解C ++的一些内容。通过引用学习传递vs按值传递。原语是通过引用还是通过值传递的?

你也应该看一下指针。你有点混淆语法。 *是de引用指针。 &安培;是获取某个对象的内存地址。

探索这些概念,您将找到问题的答案,并了解有关C ++的更多信息。

尝试查看此网站以获取一些信息。 http://www.learncpp.com/cpp-tutorial/84-access-functions-and-encapsulation/

如果您有任何其他问题,请随时告诉我。 :) 乐于帮助。

答案 1 :(得分:2)

您应该使用:

int Circle::getRadius() const{return radius}

<强>为什么吗 首先是因为你不希望你的getter修改你的对象(这是由const after()完成的,并且你不希望你的getter的调用者能够修改你的半径,实际上:

int& Circle::getRadius() const{return radius}

甚至不应该编译。它必须是:

const int& Circle::getRadius() const{return radius}

在这种情况下,返回的半径引用是const,因此调用者不能通过此getter修改半径。 虽然它完全正确,但在处理C ++中的原始类型时,通常更喜欢复制而不是保存const引用。为什么?因为原始成本的复制少于每次需要使用它时必须取消引用它。

使用:

void Circle::setRadius(int r)

<强>为什么吗 像以前一样,使用int,优先复制值以使用你必须(隐含地)对使用进行derefence的引用。

在这种情况下

CirCle* Circle::getNext() const{return next}
or 
Circle& Circle::getNext() const{return *(next)}

为什么?有一件事是肯定的,你将无法使用第二种,就像在第一种情况下你的返回值必须是const Circle&amp;。此外,您希望能够返回“无效”值。在C ++中,与Java不同,您不能返回“无效”引用。所以最好的方法是返回一个指针,如果“invalid”,它将具有“NULL”值。 之后,如果您希望调用者能够修改“下一个圆圈”,则必须使用Circle *返回。如果您不希望调用者能够修改结果,则必须使用const Circle *

const CirCle* Circle::getNext() const{return next}
or 
Circle* Circle::getNext() const{return next}

有些人认为使用返回非const指针的const方法是一件坏事。出于某些原因,我没有,但两者在语法上都是正确的。

使用:

void Circle::setNext(Circle* circle) 
{
   next = circle;
}

为什么?对于你的SetNext,它取决于你必须管理你的“下一个圈子”使用的内存(即破坏),如果它是一个外部类(我认为这是最简单的),像经理那样的例子

对于你的setRadius,只需使用:

void Circle::setRadius(int value) 
{
    radius = value;
}

[编辑:] Circle类示例: 这里的外部经理(如圆圈列表)会是什么样子:

class CircleList //Manager as I told
{
public:
    Circle* createCircle(int _radius)
    {
        Circle* circle = new circle(_radius);
        //manage here the add to the list of circle
    }

    void destroyCircle(Circle* _circle)
    {
        //Manage here the remove of the list
        delete _circle;
    }

    ~CircleList()
    {
        while( first )
        {
            destroyCircle(first);
        }
    }
private:
        Circle* first = NULL;
};

class Circle
{
public:
    Circle(int _radius) : radius(_radius) {    }
    void setNext(Circle* _circle)
    {
        next = _circle;
    }
    Circle* getNext() const
    {
        return next;
    }
    void setRadius(int _value)
    {
        radius = _value;
    }
private:
    Circle* next = NULL;
    int radius = -1;
};

这里,只有CircleList管理圆圈使用的列表和内存。如果你想要封装更多,请将setNext / getNext设为私有,将CircleList设为圆圈的朋友(再次有人会判断,让他们:p)

如果你想在Circle类中管理内存,只有当它的前身存在时才会存在一个圆圈,如果你删除一个圆圈,你将删除列表中的所有圆圈(我无法看到这个应用程序。 ..)。在这种情况下,你会有类似的东西:

 class Circle
{
public:
    Circle(int _radius) : radius(_radius) {    }
    void setNext(int _radius)
    {
        next = new Circle(radius);
    }
    void removeNext()
    {
        delete next;
        next = NULL;
    }
    Circle* getNext() const
    {
        return next;
    }
    void setRadius(int _value)
    {
        radius = _value;
    }

    ~Circle()
    {
        delete next;
    }
private:
    Circle* next = NULL;
    int radius = -1;
};

请注意,你现在在圆圈上有一个析构函数,当它破坏一个圆圈时,它会破坏列表中的所有圆圈(只有这样我才能避免泄漏和圆圈的外部“持有者”) 另外,如果你有一个非常长的列表,当析构函数调用(隐式)它的后继者的析构函数时,它可能会导致问题,你可能最终会出现堆栈溢出。

这就是为什么我告诉你,班级外部的经理对我来说是最好的解决方案,但也许其他人有更好的想法:)

答案 2 :(得分:0)

首先,在Java中,所有都是按值传递的!

如果是引用,则传递引用的值。因此,它一般被误解。

对于C ++,您可以返回/传递值或引用。在您的示例中,int值将仅通过值返回;假设你可能只需要它的值。

如果是复杂对象,可以使用引用或指针。实际上它们几乎是相同的。您可以找到来源以查看详细信息的差异,但这里让我简单地说:指针保存在C ++中以与C兼容;改为引用。所以,你可以尝试大多使用引用。

答案 3 :(得分:0)

您需要了解通过复制和引用以及使用指针来使用值的区别。

按副本传递值,比如说:

int radius = 2;
setRadius( radius );

在函数中创建2的副本。无论您在函数中对该值所做的任何更改都不会更改您在外部创建的变量半径。

指针包含一个值,该值是某个变量的内存地址。无论您使用何种类型,指针只占用内存中的4个字节。

int radius = 2;
int *radiusPtr = &radius; // radiusPtr now points to the address of radius
std::cout << *radiusPtr << std::endl; // > 2
setRadius( radiusPtr ); // Passing a pointer to setRadius

通过引用传递在某种程度上类似于指针,但它被定义为&#34;传递变量本身&#34;。您可以使用指针来更改指向的左值的值,但您可以使用引用来更改原始变量的值。您甚至可以使用对指针的引用来更改原始指针。

int radius = 2;
setRadius( radius ); // Passing by reference is done in the same way as by value, the difference is the method signature -> setRadius( int &radius );
int &radiusRef = radius;
radiusRef = 3;
std::cout << radius << std::endl; // > 3

回答使用方法。取决于您的类型和您需要的。

//If you use a setter with reference, like
void setRadius( int& radius );

//You cannot pass literal values like
setRadius( 2 );
setRadius( int(2) );

//Only variables/lvalues
int radius = 2;
setRadius( radius );

如果您使用的是更复杂的结构,则引用或指针更有意义。使用引用比复制庞大的结构更有效。

返回值时同样适用。如果您不希望用户更改属性的值,则指针或引用不是最佳选项。但是你总是可以使用const指针或引用,

const int *getRadius() const;
const int &getRadius() const;

为防止用户从外部更改半径,但仍能够使用该值。最后一个const意味着即使您使用const Circle,或const * Circle或const&amp; Circle也可以调用此函数。

我说你可以使用副本,但是对于更复杂的结构,比如Circle,考虑使用引用或指针。在你的情况下,你甚至存储指向下一个Circle的指针,所以指针应该这样做。

答案 4 :(得分:-1)

class Circle{

    public:

        void SetRadius(int const& value){ radius = value;} // 1

        int GetRadius() const {return radius;} // 2

        void SetCircle(std::shared_ptr<Circle> const& pCircle) { next = pCircle;} // 3

        std::shared_ptr<Circle> GetCircle() { return next; } // 4 

    private:

        int radius;
        std::shared_ptr<Circle> next;
}

1和3 这是你编写set函数的方法。周期。

2和4 按值返回并且不打破封装

3和4 从不使用原始指针