简体   繁体   中英

c++ Encapsulation questions

I am trying to use std::sort with custom comparison function. For this, I have a class called trySort . This is the example code for the trySort class:

trySort.h

class trySort {

public:

private:
    std::string sortThis;
};

trySort.cpp

bool sortThisAsc (const trySort & rhs , const trySort & lhs) {
    return lhs.sortThis > rhs.sortThis;
}

this will throw an error if the member sortThis is private.

If I make sortThis a public member like this...

trySort.h

class trySort {

public:
      std::string sortThis;

private:           
};

trySort.cpp

bool sortThisAsc (const trySort & rhs , const trySort & lhs) {
    return lhs.sortThis > rhs.sortThis;
}

...It will work. It appears as though I make sortThis a public member.

So my question is: If I were to do this, am I not encapsulating my data?

If so, what are some other possible approachs other than putting it as a public member?

You can add operator > to trySort class.

trySort.h

class trySort {

public:
    bool operator >(trySort const &other) {
        return sortThis > other.sortThis;
    }  
private:
    std::string sortThis;
}

If you need more flexibility (some other kinds of comparisons), just encapsulate sortThis with a getter function.

trySort.h

class trySort {

public:
    std::string const &getSortThis() const {
        return sortThis;
    }

private:
    std::string sortThis;
}

If you are absolutely sure that sortThis will always be immutable through the course of a project, thus initialized in the constructor, you can leave it as a public const member, but in most cases this is very speculative approach.

trySort.h

class trySort {

public:
    trySort(std::string const sortThis)
        : sortThis(sortThis) {
    }

    const std::string sortThis;
}

Or you can do it with friend , but I would leave it as a last resort, since in most cases it turns out to represent excessive intimacy (there is always some other approach you can take to avoid using friend s). Using friend can be appropriate in some circumstances, but it never the less breaks encapsulation, with the difference that friend clause signals to class' clients that breakage was intentional.

Use friend :

class trySort {
friend bool sortThisAsc (const trySort & rhs , const trySort & lhs);

private:
       std::string sortThis;
}

It will give access only to this function and not to anything else

EDIT This gets rid of the compilation error you mentioned, but only non-member functions can be passed to std::sort(), so this doesn't quite work.

In your cpp file, change the function definition from

bool sortThisAsc (const trySort & rhs , const trySort & lhs) {

to

bool trySort::sortThisAsc(const trySort & rhs, const trySort & lhs) {

Without the trySort:: the function isn't defined in the trySort class scope (ie outside that class), so the compiler complains if you try to access private variables in trySort .

This way, you can keep it as a private method, as you originally asked for.

There are at least two alternatives. Either you can declare a public getter to this data member as for example

class trySort {

public:
       const std::string & get_string() const { return sortThis; }

private:
       std::string sortThis;
}

and then in function sortThisAsc to write

bool sortThisAsc (const trySort & rhs , const trySort & lhs) {
    return lhs.get_string() > rhs.get_string();
}

Or you can declare the function as a friend function of the class

class trySort {

public:
       friend bool sortThisAsc (const trySort & rhs , const trySort & lhs);

private:
       std::string sortThis;
}

In this case the function definition will not be changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM