2017-09-05 87 views
2

我读到,因为朋友函数不是一个成员函数,所以它永远不会被继承。我想下面的代码继承和朋友函数在C + +

#include <iostream> 
#include <string> 

using namespace std; 

class Base { 
    char *m_str; 
public: 
    Base(void): m_str("Base Default") { } 
    friend ostream & operator<<(ostream & , const Base &); 
}; 

ostream & operator<<(ostream &os , const Base &b) { 
    os << "Base String : " << b.m_str << endl; 
    return os; 
} 

class Derived : public Base { 
    char *m_dstr; 
public: 
    Derived(void): Base(), m_dstr("Derived Default") { } 
}; 
int main(void) { 
    Derived obj3; 
    cout << obj3; 
    return 0; 
} 

和O/P是: - 基础线:基本的默认

我的理解是,我应该在编译时已经得到了错误。但我认为它的工作原因是编译器内部使用派生对象作为基类引用。这个理由是正确的吗?

请注意,我直接分配的字符串常量地址指针,而不是复制串入动态分配的内存。这只是为了实验目的:对

+0

尝试使用非朋友的非会员功能。 – juanchopanza

+0

“朋友函数不是成员函数,所以它永远不会被继承”。这相当具有误导性。好友功能只是一个功能,可以像任何其他功能一样调用。友谊只在功能主体内部起作用。 –

+0

“将字符串文字地址指向指针而不是将字符串复制到动态分配的内存”:您不需要复制文字字符串,但应该使用'const char *'而不是'char *'。 – Jarod42

回答

1

operator<<是一个免费的功能。因此,它既不被遗传也不被视为与其他任何自由功能不同(不论友谊)。

现在,当编译器处理语句时,通常会发生重载解析。为此,检查参数的类型,在这种情况下是std::ostreamDerived。接下来,考虑所有可用函数,编译器检查它们是否可以接受这些类型的参数。由于Derived继承Base和上转换是隐式的(可能由编译器没有你明确声明来执行),每一个功能,需要一个Base(或const /非const指针/参考Base)也采取Derived和因此是有效的匹配。这正是你的情况operator<<

接下来,所有匹配的重载都从最佳匹配到最差(但仍然有效)匹配。比赛的质量在此由编程语言指定。如果有一个最佳匹配,则选择一个。在两个或两个以上重载同样好的情况下,重载解析是不明确的,编译器无法决定选择哪一个。在你的特定情况下,只有一个功能,那就是选择一个功能。

你会添加一个附加函数ostream& operator<<(ostream&, const Derived&),那个编译器会选择一个函数,因为它更适合类型为std::ostreamDerived的参数。

+0

@ Rakete1111这是错误的。如果用公共getter替换对'b.m_str'的​​访问,没有朋友就可以很好地编译。 –

+0

没关系我,我认为这个功能是在课堂上定义的。抱歉! – Rakete1111

+0

OP从来没有问过关于友善的继承。否则这个问题将是重复的。 –

2

这里没有什么奇怪的事情发生在这里。

事实上,operator<<是一个免费的功能是不是Base一部分,Base只指定该函数是说类的朋友。

然后您继续调用此函数并为其提供一个Derived对象。 A Derived对象 a Base对象,因此operator<<的指定超载是有效的。这与继承功能无关,与friend无关。

试试这个与任何其他免费功能采取Base它会同样有效。