C++ has-a 关系的建立(私有继承)中遇到了问题

#include <iostream>
#include <valarray>
using namespace std;
//C++继承模板类的原代码

class Student :private string, private valarray<double>
{
public:
    string name;
    //注意这里只是模板类声明,并不是具体实现,因此没有开辟空间
    valarray <double> score;
public:
    //构造函数这里我们其实可以有很多的选择,下面写出一些,这里选择列表初始化
    //默认的构造函数,没有名字,没有成绩
    Student(): string("no name"), valarray<double>() {
        cout << "默认构造函数的调用" << endl;
    }

    //可以初始化名字和成绩的数量
    Student(const string & s, int n) : string(s), valarray<double>(n) {
        cout << "(const string & s, int n)的调用" << endl;
    }

    //初始化成绩的数量
    explicit Student(int n) : string("na name"), valarray<double>(n) {
        cout << "Student(int n)的调用" << endl;
    }

    //既然可以用string &来构造string初始化string,那当然可以用 valarray<double> & 来初始化 valarray <double>
    //与string 一样,列表初始化调用其构造函数
    Student(const string & s, valarray<double> & v) : string(s), valarray<double>(v) {
        cout << "(const string & s, valarray<double> & v)的调用" << endl;
    }

    //可以提供一个C的接口,让类的健壮性更强
    //让所有成绩全初始化为val
    Student(const char * s, double * val, int n) : string(s), valarray<double>(val,n) {
        cout << "(const char * s, double * val, int n)的调用" << endl;
    }

    //因为在类中没有用到new操作,所以写一个空实现的析构函数即可
    ~Student() = default;

    //类方法,我们用的私有继承,所以string类中的类方法和valarray中的类方法全部变为私有,但我们可以在派生类中提供对外的接口
    //假设写一个求平均分的类方法,虽然不能Student::string::length(),但我们可以这样做
    double average() const; //在类中实现的函数会自动转换为内联函数,这里在类外写

    //友元函数虫重载 <<
    friend ostream & operator<<(ostream & os,const Student & s);
};


ostream & operator<<(ostream & os,const Student & s)
{
    os << "name is : " << s.name << endl;
    os << "score is : " << endl;
    for(int i=0;s.score.size();i++){
        cout << s.score[i] << " ";
    }
    return os;
}
//使用类方法
double Student::average() const
{
    //return score.sum() / score.size();
    return valarray<double>::sum() / (double)valarray<double>::size();
}
int main()
{
    typedef Student S;
    //下面用各种构造函数来进行对象的初始化
    //默认构造函数
    S s1;
    S s2 = S{"lilei", 3};
    S s3 {3};
    valarray<double> v(3);
    S s4 {"liha", v};
    double sor = 80.4;
    S s5 = {"hello", &sor, 3};
    cout << s5.average();
}

https://img-blog.csdnimg.cn/b1569c6bff7446b095b061202c378511.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASkFONjA1NQ==,size_20,color_FFFFFF,t_70,g_se,x_16
 这样看是没错

但在有这样的警告

https://img-blog.csdnimg.cn/59715f22729b416387c09abe70c11b61.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASkFONjA1NQ==,size_14,color_FFFFFF,t_70,g_se,x_16

 显示我们定义的构造函数没有使用,average显示出来的也不对,不知道大佬们有没有什么解决问题的办法,帮帮孩子把(快哭了)

img


你的score在哪里赋值?

//test.h
#pragma once
#include "stdafx.h" //非vs2015可以去掉这个头文件
#include <iostream>
#include <valarray>

using namespace std;
//C++继承模板类的原代码

class Student :private string, private valarray<double>
{
public:
    string name;
    //注意这里只是模板类声明,并不是具体实现,因此没有开辟空间
    valarray <double> score;
public:
    //构造函数这里我们其实可以有很多的选择,下面写出一些,这里选择列表初始化
    //默认的构造函数,没有名字,没有成绩
    Student() : string("no name"), valarray<double>() {
        cout << "默认构造函数的调用" << endl;
    }

    //可以初始化名字和成绩的数量
    Student(const string & s, int n) : string(s), valarray<double>(n) {
        cout << "(const string & s, int n)的调用" << endl;
    }

    //初始化成绩的数量
    explicit Student(int n) : string("na name"), valarray<double>(n) {
        cout << "Student(int n)的调用" << endl;
    }

    //既然可以用string &来构造string初始化string,那当然可以用 valarray<double> & 来初始化 valarray <double>
    //与string 一样,列表初始化调用其构造函数
    Student(const string & s, valarray<double> & v) : string(s), valarray<double>(v) {
        cout << "(const string & s, valarray<double> & v)的调用" << endl;
    }

    //可以提供一个C的接口,让类的健壮性更强
    //让所有成绩全初始化为val
    Student(const char * s, double * val, int n) : string(s), valarray<double>(val, n) {
        cout << "(const char * s, double * val, int n)的调用" << endl;
    }

    //因为在类中没有用到new操作,所以写一个空实现的析构函数即可
    ~Student() = default;

    //类方法,我们用的私有继承,所以string类中的类方法和valarray中的类方法全部变为私有,但我们可以在派生类中提供对外的接口
    //假设写一个求平均分的类方法,虽然不能Student::string::length(),但我们可以这样做
    double average() const; //在类中实现的函数会自动转换为内联函数,这里在类外写

                            //友元函数虫重载 <<
    friend ostream & operator<<(ostream & os, const Student & s);
};


ostream & operator<<(ostream & os, const Student & s)
{
    os << "name is : " << s.name.c_str() << endl;
    os << "score is : " << endl;
    for (int i = 0; s.score.size(); i++) {
        cout << s.score[i] << " ";
    }
    return os;
}
//使用类方法
double Student::average() const
{
    //return score.sum() / score.size();
    double a = valarray<double>::sum();
    double b = (double)valarray<double>::size();
    return valarray<double>::sum() / (double)valarray<double>::size();
}
//main.cpp
#include "stdafx.h"
#include"test.h"
#include <iostream>
using namespace std;

int main()
{
    typedef Student S;
    //下面用各种构造函数来进行对象的初始化
    //默认构造函数
    S s1;
    S s2 = S{ "lilei", 3 };
    S s3{ 3 };
    valarray<double> v(3);
    S s4{ "liha", v };
    double sor = 80.4;
    S s5 = { "hello", &sor, 3 };
    cout << s5.average();
    system("pause");
    return 0;
}

不明白你为啥学生类要去继承这两个类,怎么想的呢???

代码使用了c++11的语法,请用支持c++11标准的编译器

img

大致明白你的问题了,建议去理解什么是类型,什么是类型的实例(或者是对象)
你搞混了类型和对象。

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632