返回指向类中的类的指针
Posted
技术标签:
【中文标题】返回指向类中的类的指针【英文标题】:Returning a pointer to a class within a class 【发布时间】:2013-11-26 01:59:40 【问题描述】:这是我第一次做这样的事情,所以我有点不确定我需要如何做。我有一个非常简单的类,其中包含一些简单的值和一些 getter:
class Nucleotide
private:
char Base;
int Position;
int Polymorphic;
public:
Nucleotide(char ch, int pos);
int getPos();
char getBase();
int getPoly();
;
这个类存在于另一个包含它们向量的类中:
class NucleotideSequence
private:
std::string Name;
std::vector<Nucleotide> Sequence;
public:
NucleotideSequence(std::string name, std::vector<Nucleotide> seq);
std::string getName();
Nucleotide getBase(int pos1);
;
我希望名为 getBase 的第二个类的方法能够接受一个整数——比如 1,并返回向量中的第一个 Nucleotide 对象。我写的如下:
Nucleotide NucleotideSequence::getBase(int pos1)
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
if(pos1 == (*i).getPos())
return i; // Return a pointer to the correct base.
我已经将 Nucleotide 作为返回类型,但我真的想知道我应该如何更改它 - 因为如果我因为传递值而返回 核苷酸,它会不会只返回向量中那个位置的对象的副本?所以我宁愿返回一个指针/引用。我在循环中使用了一个迭代器,所以我应该只返回一个带有迭代器值的指针吗?我该怎么做呢?在函数中我返回 i 但我应该返回 i& 吗?我不确定具体细节 - 大概如果我返回一个指针,我的返回类型需要是 Nucleotide* 或者 Nucleotide& 因为 & 表示地址?我已经考虑过了并阅读了 Cpp tuts,但我仍然有点不确定正确的答案。
谢谢, 本。
【问题讨论】:
你不能以某种方式使用Sequence[pos1]
吗?
【参考方案1】:
您必须通过引用返回核苷酸:
Nucleotide & NucleotideSequence::getBase(int pos1)
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
if(pos1 == (*i).getPos())
return *i; // Notice the *i instead of i
reference 的工作方式与指针非常相似(允许您传递实际对象,而不是其副本),但不能为 null 且不能指向不存在的对象,因此它比指针更安全指针。
但请注意,如果您没有找到所需的Nucleotide
,则不会返回任何内容,这通常不是一个好主意。在这种情况下,使用指针实际上可能是一个更好的主意:
Nucleotide * NucleotideSequence::getBase(int pos1)
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
if(pos1 == (*i).getPos())
return &(*i);
return nullptr;
【讨论】:
【参考方案2】:您不返回指针,而是尝试返回迭代器。并且该函数被声明为返回一个实例而不是一个指针。此外,如果您没有找到 Nucleotide
,如果您尝试使用“返回”值,则根本不会返回任何导致未定义行为的内容。
您可以更改函数以返回一个指针、一个引用或只是一个值(复制就像它没有声明一样。
您也可以进行更改,以便该函数将 Nucleotide
作为参数,然后返回一个布尔指示符(如果找到或未找到)。
bool NucleotideSequence::getBase(int pos1, Nucleotide& n)
for (...)
if (...)
n = *i;
return true;
return false; // Not found
【讨论】:
你的灵魂的缺点是你实际上需要一个现有的核苷酸来传递给这个函数。我想到了这个解决方案,在这种情况下,使用 C# 风格的Nucleotyde::Empty
会很有用,但可能会使事情复杂化。
@Spook 当然。这样做的主要缺点是无法链接调用(即让函数用作表达式的一部分)。虽然在返回指针时不建议这样做,但在这种情况下我看不出有太大的区别。【参考方案3】:
就您的问题而言,按照其他人的建议返回引用 (&) 是解决方案。
为了改进您的代码,我也建议进行更改:
要么使用 operator[],要么使用 std::vector 中的 at()。
因此,你可以直接说:
return Sequence[pos1]; 或 return Sequence.at(pos1);
【讨论】:
这更像是一个评论而不是一个答案,但是一个非常正确的答案。 不完全是,因为 getPos() 方法与序列中核苷酸的位置不相关。 @CompuChip 我仍然不允许对问题发表评论,因此必须在此处发布。 @SirDarius 上面问题中的这条语句证明了我的观点,“我希望名为 getBase 的第二个类的方法能够接受一个整数 - 比如说 1,并返回第一个 Nucleotide 对象矢量。” @gargankit 那么这个问题自相矛盾,应该澄清一下。【参考方案4】:为了提高效率,您的代码将受益于引用的一些使用。 getBase
方法签名应如下所示:
const Nucleotide& NucleotideSequence::getBase(int pos1)
NucleotideSequence
构造函数签名应如下所示:
NucleotideSequence(const std::string& name, const std::vector<Nucleotide>& seq);
而getName
方法是这样的:
const std::string& getName();
(尽管return value optimisation 可能会让它变得不那么重要。)
至于getBase的内容,将代码分解为:
const Nucleotide* NucleotideSequence::getBase(int pos1)
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); ++i)
Nucleotide& ref = *i; //Get a reference to the object this iterator points to
if(pos1 == ref.getPos()) //compare its base to the argument
return &ref; // Return a pointer to the correct object.
return NULL; //or null if we didn't find the object we wanted
【讨论】:
以上是关于返回指向类中的类的指针的主要内容,如果未能解决你的问题,请参考以下文章