使用友元函数迭代另一个类的私有成员

时间:2017-02-05 14:25:33

标签: c++ iterator friend-function

我在下面的类中声明了一个友元函数。

班级模型

func createP12(secCertificate: SecCertificate, secPrivateKey: SecKey) {
    // Read certificate
    // Convert sec certificate to DER certificate
    let derCertificate = SecCertificateCopyData(secCertificate)
    // Create strange pointer to read DER certificate with OpenSSL
    // data must be a two-dimensional array containing the pointer to the DER certificate as single element at position [0][0]
    let certificatePointer = CFDataGetBytePtr(derCertificate)
    let certificateLength = CFDataGetLength(derCertificate)
    let certificateData = UnsafeMutablePointer<UnsafePointer<UInt8>?>.allocate(capacity: 1)
    certificateData.pointee = certificatePointer
    // Read DER certificate
    let certificate = d2i_X509(nil, certificateData, certificateLength)
    // Print certificate
    X509_print_fp(stdout, certificate)
    // Read private key
    // Convert sec key to PEM key
    let tempTag = "bundle.temp"
    let tempAttributes = [
        kSecClass: kSecClassKey,
        kSecAttrApplicationTag: tempTag,
        kSecAttrKeyType: kSecAttrKeyTypeRSA,
        kSecValueRef: secPrivateKey,
        kSecReturnData: kCFBooleanTrue
        ] as NSDictionary
    var privateKeyRef: AnyObject?
    // Store private key in keychain
    SecItemDelete(tempAttributes)
    guard SecItemAdd(tempAttributes, &privateKeyRef) == noErr else {
        NSLog("Cannot store private key")
        return
    }
    // Get private key data
    guard let privateKeyData = privateKeyRef as? Data else {
        NSLog("Cannot get private key data")
        return
    }
    let pemPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\n\(privateKeyData.base64EncodedString())\n-----END RSA PRIVATE KEY-----\n"
    // Delete private key in keychain
    SecItemDelete(tempAttributes)
    let privateKeyBuffer = BIO_new(BIO_s_mem())
    pemPrivateKey.data(using: .utf8)!.withUnsafeBytes({ (bytes: UnsafePointer<Int8>) -> Void in
        BIO_puts(privateKeyBuffer, bytes)
    })
    let privateKey = PEM_read_bio_PrivateKey(privateKeyBuffer, nil, nil, nil)
    // !!! Remove in production: Print private key
    PEM_write_PrivateKey(stdout, privateKey, nil, nil, 0, nil, nil)
    // Check if private key matches certificate
    guard X509_check_private_key(certificate, privateKey) == 1 else {
        NSLog("Private key does not match certificate")
        return
    }
    // Set OpenSSL parameters
    OPENSSL_add_all_algorithms_noconf()
    ERR_load_crypto_strings()
    // Create P12 keystore
    let passPhrase = UnsafeMutablePointer(mutating: ("" as NSString).utf8String)
    let name = UnsafeMutablePointer(mutating: ("SSL Certificate" as NSString).utf8String)
    guard let p12 = PKCS12_create(passPhrase, name, privateKey, certificate, nil, 0, 0, 0, 0, 0) else {
        NSLog("Cannot create P12 keystore:")
        ERR_print_errors_fp(stderr)
        return
    }
    // Save P12 keystore
    let fileManager = FileManager.default
    let tempDirectory = NSTemporaryDirectory() as NSString
    let path = tempDirectory.appendingPathComponent("ssl.p12")
    fileManager.createFile(atPath: path, contents: nil, attributes: nil)
    guard let fileHandle = FileHandle(forWritingAtPath: path) else {
        NSLog("Cannot open file handle: \(path)")
        return
    }
    let p12File = fdopen(fileHandle.fileDescriptor, "w")
    i2d_PKCS12_fp(p12File, p12)
    fclose(p12File)
    fileHandle.closeFile()
}

#include "fileio.h" class fileio; class model { std::vector<element>m_elements; public: friend void fileio::element_iterator(); } element_iterator()的公共函数。

班级档案

class fileio

#include "model.h" class model; class fileio { model* m_model; public: fileio(model*); void element_iterator(); } 函数定义如下。

element_iterator()

我想使用friend函数从另一个类迭代void fileio::element_iterator() { for(auto &iter : m_model->m_elements) { //some functions } } 。但是我收到的错误如下:

错误:

m_elements

修改
如果没有fileio.h中 model.h : error: invalid use of incomplete type 'class fileio' friend void fileio::read_boundary(); model.h : error: forward declaration of 'class fileio' class fileio; modell.h : In member function 'void fileio::read_boundary()': cmodel.h : error: 'std::vector<element> model::m_elements' is private std::vector<element>m_elements; fileio.cpp: error: within this context for(auto iter:m_model->m_elements) 的前向声明,则会产生另一组错误,如下所示:

class model

如果我注释掉友元函数声明及其定义,那么程序将运行没有错误。 我该如何解决?

1 个答案:

答案 0 :(得分:2)

而不是fileio中的前向声明 model.h,请包含其完整定义。

// fileio.h
class model;
class fileio
{
    model* m_model;
    public:
    void element_iterator();
};

// model.h
#include "fileio.h"
class model
{
    std::vector<int >m_elements;
    public:
    friend void fileio::element_iterator();
};

wandbox example

或者,您可以将整个fileio课程设为friend - 这样您就可以使用其转发声明,这可能是您想要的,具体取决于您的真实的情况。

// model.h
class fileio;
class model
{
    std::vector<int >m_elements;
    public:
    friend class fileio;
};

// fileio.h
class model;
class fileio
{
    model* m_model;
    public:
    void element_iterator();
};

wandbox example